Compare commits
208 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29d61656fe | |||
| 52e21a8ced | |||
| 60974e14fd | |||
| 3eadddb784 | |||
| 20a6e83f86 | |||
| 7548ffdd1b | |||
| 8a647790ab | |||
| 92b64abde5 | |||
| 1d82dc7cc6 | |||
| e54db103c8 | |||
| 9e480433fc | |||
| 92e25dfad8 | |||
| daac004cd6 | |||
| 0457b85abf | |||
| 89003e83f6 | |||
| 1a42ce1151 | |||
| 217f046290 | |||
| 4c9e975bcb | |||
| ba8878cafa | |||
| 7449fd8b12 | |||
| d1dbe60b4e | |||
| 1187aa3c70 | |||
| 7342601ea7 | |||
| 35d1e8992a | |||
| 10d6abe252 | |||
| ced5fc1690 | |||
| c5e3ae6f43 | |||
| b03b731601 | |||
| 18eca61f0e | |||
| 0f6c209972 | |||
| 6300fd3844 | |||
| 611e6d31cd | |||
| 22e7df8bb8 | |||
| 843ec6e8ad | |||
| 4ee91187ba | |||
| f9278ccca3 | |||
| 3833e9491c | |||
| 26ef0dcdb0 | |||
| 5b0de5d015 | |||
| 5f65870086 | |||
| 897c93c803 | |||
| 719fe1e215 | |||
| 2fb4bbf2e4 | |||
| 0e6d9044b6 | |||
| 7381b1e96c | |||
| 64f9204bf2 | |||
| 5d641f3c79 | |||
| b62409e738 | |||
| 4c7a24ff3b | |||
| c0cb56bacb | |||
| 89f0483e3b | |||
| cf1ea5eb60 | |||
| c82ff20752 | |||
| 916abecd67 | |||
| eb031d173c | |||
| 64937fcfc0 | |||
| 7f1a377845 | |||
| bb7e905b4a | |||
| 65b269fef0 | |||
| b5cd679440 | |||
| 9018d2525b | |||
| 4c9a0ef270 | |||
| f4f6aefb15 | |||
| a80fdadfd6 | |||
| f416b43ccf | |||
| d51dcd3e9c | |||
| a9ef8bfcf0 | |||
| d159f8e218 | |||
| 3fa7c89a20 | |||
| 63eb6d836c | |||
| 702319aacc | |||
| 8fb93c6fcb | |||
| c9cdcc6ecf | |||
| 72a5a24c4f | |||
| b48a3022bb | |||
| 488ba1d18b | |||
| 5618ffbb3a | |||
| 58675b10d1 | |||
| cdfca99b11 | |||
| 59190fa728 | |||
| 99e678b430 | |||
| 074c1badfb | |||
| c058bfc0cc | |||
| 67c7ecf1ff | |||
| 676357f878 | |||
| a22ad22aaa | |||
| fa81835e0d | |||
| ac5f7a07e2 | |||
| d421cf68be | |||
| c262e3022d | |||
| 08cb8e9f9a | |||
| 44cd91369c | |||
| 37b014b986 | |||
| b4babe8596 | |||
| 13bc8e4636 | |||
| b45e06c65e | |||
| da58f03800 | |||
| ea899192dc | |||
| cc61dcd094 | |||
| 6c8d09bd20 | |||
| 9cc6c4a8b5 | |||
| d9c88b6b0c | |||
| f53da27c6c | |||
| 6a45539bf5 | |||
| 5ab99e01e4 | |||
| 9d09db0561 | |||
| be0a25457d | |||
| aa39d26cbd | |||
| 9811f14708 | |||
| dd38b1a2a0 | |||
| 66e6d45a68 | |||
| 87b65118fd | |||
| 90656cf6b8 | |||
| 0fbee2543c | |||
| 7923c9b8c3 | |||
| 57943a4cbe | |||
| 95c0bbcc3c | |||
| ae87ceac0b | |||
| 4a53a00a17 | |||
| df39cdcb63 | |||
| 5bc8d42069 | |||
| 15a331f1a3 | |||
| 7038117d4c | |||
| 92733c9c60 | |||
| 4cc050e804 | |||
| d2018e2104 | |||
| dd6f403da0 | |||
| a09cf6feee | |||
| 61a65ec3fe | |||
| f66d5c23ab | |||
| fa180a4830 | |||
| 263a155f9c | |||
| d6514ae3b6 | |||
| a5e577d6df | |||
| 1fbcb367d5 | |||
| 4904d3fabf | |||
| b2cda7e069 | |||
| d1a7324062 | |||
| 7df5afa46f | |||
| 2349cebb57 | |||
| bc17e06958 | |||
| b09e6b3fbf | |||
| e1f2f3231b | |||
| de73c4c316 | |||
| 440c897fd0 | |||
| c7c2155f9b | |||
| 3adc4a731c | |||
| cc7239cb12 | |||
| 0e3d1678bb | |||
| a6dbac872e | |||
| 0f7f5097b6 | |||
| 190568635e | |||
| edbd4e9274 | |||
| 8c5e602aa1 | |||
| 69cfa2972d | |||
| d817b0b91e | |||
| 5b27e6b5b5 | |||
| 0f266df8d1 | |||
| 6f3a2fffc3 | |||
| da05d3b5c2 | |||
| 515ab9de9a | |||
| 7cf81559cf | |||
| e42415e4ad | |||
| 6348e30331 | |||
| 432d65ee41 | |||
| 40df5b91ca | |||
| c864a9f73b | |||
| 35c4c1cad1 | |||
| b10fb51d87 | |||
| ce6d9a20ab | |||
| 01f5b9cce2 | |||
| ad62a11395 | |||
| 615cb07384 | |||
| 6792922263 | |||
| d009613055 | |||
| 937251f515 | |||
| 4c21ec1595 | |||
| 688d8fea2d | |||
| 5a5cda8845 | |||
| f7cb7fc6b7 | |||
| 7479278133 | |||
| a472f03345 | |||
| 74fffe24a3 | |||
| dc194d3d2d | |||
| 7230b01b30 | |||
| c5546bbf80 | |||
| b99342e507 | |||
| 4e2b1eebfd | |||
| b6bf83210a | |||
| 11535a40f5 | |||
| c81aad8b9c | |||
| d58c68efda | |||
| e4ab518ee5 | |||
| 38f30f6b3a | |||
| ec34ffb990 | |||
| 8e0429db2d | |||
| 9404856979 | |||
| 206870e3d2 | |||
| e0934f3fea | |||
| dad9689ff2 | |||
| 2b9aba5e9a | |||
| 1c70cce8c9 | |||
| f7ee7a9cec | |||
| 2534a3e444 | |||
| 300a993a15 | |||
| c7e5c7930c | |||
| 632302a672 | |||
| 76b53614f3 |
@@ -1,3 +1,6 @@
|
||||
# We can always generate the documentation from source.
|
||||
docs/
|
||||
|
||||
# Mac OS X
|
||||
.DS_Store
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 08/01/2010.
|
||||
// Copyright 2010 Alex Rozanski http://perspx.com
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "PXSourceList.h"
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
@protocol NSApplicationDelegate <NSObject> @end
|
||||
#endif
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate, PXSourceListDataSource, PXSourceListDelegate> {
|
||||
IBOutlet PXSourceList *sourceList;
|
||||
IBOutlet NSTextField *selectedItemLabel;
|
||||
|
||||
NSMutableArray *sourceListItems;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,53 +0,0 @@
|
||||
//
|
||||
// SourceListItem.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 08/01/2010.
|
||||
// Copyright 2010 Alex Rozanski http://perspx.com
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
/*An example of a class that could be used to represent a Source List Item
|
||||
|
||||
Provides a title, an identifier, and an icon to be shown, as well as a badge value and a property to determine
|
||||
whether the current item has a badge or not (`badgeValue` is set to -1 if no badge is shown)
|
||||
|
||||
Used to form a hierarchical model of SourceListItem instances – similar to the Source List tree structure
|
||||
and easily accessible by the data source with the "children" property
|
||||
|
||||
SourceListItem *parent
|
||||
- SourceListItem *child1;
|
||||
- SourceListItem *child2;
|
||||
- SourceListItem *childOfChild2;
|
||||
- SourceListItem *anotherChildOfChild2;
|
||||
- SourceListItem *child3;
|
||||
|
||||
*/
|
||||
|
||||
@interface SourceListItem : NSObject {
|
||||
NSString *title;
|
||||
NSString *identifier;
|
||||
NSImage *icon;
|
||||
NSInteger badgeValue;
|
||||
|
||||
NSArray *children;
|
||||
}
|
||||
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
@property (nonatomic, copy) NSString *identifier;
|
||||
@property (nonatomic, retain) NSImage *icon;
|
||||
@property NSInteger badgeValue;
|
||||
|
||||
@property (nonatomic, copy) NSArray *children;
|
||||
|
||||
//Convenience methods
|
||||
+ (id)itemWithTitle:(NSString*)aTitle identifier:(NSString*)anIdentifier;
|
||||
+ (id)itemWithTitle:(NSString*)aTitle identifier:(NSString*)anIdentifier icon:(NSImage*)anIcon;
|
||||
|
||||
|
||||
- (BOOL)hasBadge;
|
||||
- (BOOL)hasChildren;
|
||||
- (BOOL)hasIcon;
|
||||
|
||||
@end
|
||||
@@ -1,100 +0,0 @@
|
||||
//
|
||||
// SourceListItem.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 08/01/2010.
|
||||
// Copyright 2010 Alex Rozanski http://perspx.com
|
||||
//
|
||||
// GC-enabled code revised by Stefan Vogt http://byteproject.net
|
||||
//
|
||||
|
||||
#import "SourceListItem.h"
|
||||
|
||||
|
||||
@implementation SourceListItem
|
||||
|
||||
@synthesize title;
|
||||
@synthesize identifier;
|
||||
@synthesize icon;
|
||||
@synthesize badgeValue;
|
||||
@synthesize children;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Init/Dealloc/Finalize
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if(self=[super init])
|
||||
{
|
||||
badgeValue = -1; //We don't want a badge value by default
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
+ (id)itemWithTitle:(NSString*)aTitle identifier:(NSString*)anIdentifier
|
||||
{
|
||||
SourceListItem *item = [SourceListItem itemWithTitle:aTitle identifier:anIdentifier icon:nil];
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
+ (id)itemWithTitle:(NSString*)aTitle identifier:(NSString*)anIdentifier icon:(NSImage*)anIcon
|
||||
{
|
||||
SourceListItem *item = [[[SourceListItem alloc] init] autorelease];
|
||||
|
||||
[item setTitle:aTitle];
|
||||
[item setIdentifier:anIdentifier];
|
||||
[item setIcon:anIcon];
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[title release];
|
||||
[identifier release];
|
||||
[icon release];
|
||||
[children release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)finalize
|
||||
{
|
||||
title = nil;
|
||||
identifier = nil;
|
||||
icon = nil;
|
||||
children = nil;
|
||||
|
||||
[super finalize];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Custom Accessors
|
||||
|
||||
- (BOOL)hasBadge
|
||||
{
|
||||
return badgeValue!=-1;
|
||||
}
|
||||
|
||||
- (BOOL)hasChildren
|
||||
{
|
||||
return [children count]>0;
|
||||
}
|
||||
|
||||
- (BOOL)hasIcon
|
||||
{
|
||||
return icon!=nil;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Custom Accessors
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: %p | identifier = %@ | title = %@ >", [self class], self, self.identifier, self.title];
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 08/01/2010.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "PXSourceList.h"
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate, PXSourceListDataSource, PXSourceListDelegate>
|
||||
|
||||
@end
|
||||
@@ -3,11 +3,20 @@
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 08/01/2010.
|
||||
// Copyright 2010 Alex Rozanski http://perspx.com
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "SourceListItem.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (weak, nonatomic) IBOutlet PXSourceList *sourceList;
|
||||
@property (weak, nonatomic) IBOutlet NSTextField *selectedItemLabel;
|
||||
|
||||
@property (strong, nonatomic) NSMutableArray *sourceListItems;
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
@@ -16,37 +25,37 @@
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[selectedItemLabel setStringValue:@"(none)"];
|
||||
[self.selectedItemLabel setStringValue:@"(none)"];
|
||||
|
||||
sourceListItems = [[NSMutableArray alloc] init];
|
||||
self.sourceListItems = [[NSMutableArray alloc] init];
|
||||
|
||||
//Set up the "Library" parent item and children
|
||||
SourceListItem *libraryItem = [SourceListItem itemWithTitle:@"LIBRARY" identifier:@"library"];
|
||||
SourceListItem *musicItem = [SourceListItem itemWithTitle:@"Music" identifier:@"music"];
|
||||
PXSourceListItem *libraryItem = [PXSourceListItem itemWithTitle:@"LIBRARY" identifier:@"library"];
|
||||
PXSourceListItem *musicItem = [PXSourceListItem itemWithTitle:@"Music" identifier:@"music"];
|
||||
[musicItem setIcon:[NSImage imageNamed:@"music.png"]];
|
||||
SourceListItem *moviesItem = [SourceListItem itemWithTitle:@"Movies" identifier:@"movies"];
|
||||
PXSourceListItem *moviesItem = [PXSourceListItem itemWithTitle:@"Movies" identifier:@"movies"];
|
||||
[moviesItem setIcon:[NSImage imageNamed:@"movies.png"]];
|
||||
SourceListItem *podcastsItem = [SourceListItem itemWithTitle:@"Podcasts" identifier:@"podcasts"];
|
||||
PXSourceListItem *podcastsItem = [PXSourceListItem itemWithTitle:@"Podcasts" identifier:@"podcasts"];
|
||||
[podcastsItem setIcon:[NSImage imageNamed:@"podcasts.png"]];
|
||||
[podcastsItem setBadgeValue:10];
|
||||
SourceListItem *audiobooksItem = [SourceListItem itemWithTitle:@"Audiobooks" identifier:@"audiobooks"];
|
||||
[podcastsItem setBadgeValue:@10];
|
||||
PXSourceListItem *audiobooksItem = [PXSourceListItem itemWithTitle:@"Audiobooks" identifier:@"audiobooks"];
|
||||
[audiobooksItem setIcon:[NSImage imageNamed:@"audiobooks.png"]];
|
||||
[libraryItem setChildren:[NSArray arrayWithObjects:musicItem, moviesItem, podcastsItem,
|
||||
audiobooksItem, nil]];
|
||||
|
||||
//Set up the "Playlists" parent item and children
|
||||
SourceListItem *playlistsItem = [SourceListItem itemWithTitle:@"PLAYLISTS" identifier:@"playlists"];
|
||||
SourceListItem *playlist1Item = [SourceListItem itemWithTitle:@"Playlist1" identifier:@"playlist1"];
|
||||
PXSourceListItem *playlistsItem = [PXSourceListItem itemWithTitle:@"PLAYLISTS" identifier:@"playlists"];
|
||||
PXSourceListItem *playlist1Item = [PXSourceListItem itemWithTitle:@"Playlist1" identifier:@"playlist1"];
|
||||
|
||||
//Create a second-level group to demonstrate
|
||||
SourceListItem *playlist2Item = [SourceListItem itemWithTitle:@"Playlist2" identifier:@"playlist2"];
|
||||
SourceListItem *playlist3Item = [SourceListItem itemWithTitle:@"Playlist3" identifier:@"playlist3"];
|
||||
PXSourceListItem *playlist2Item = [PXSourceListItem itemWithTitle:@"Playlist2" identifier:@"playlist2"];
|
||||
PXSourceListItem *playlist3Item = [PXSourceListItem itemWithTitle:@"Playlist3" identifier:@"playlist3"];
|
||||
[playlist1Item setIcon:[NSImage imageNamed:@"playlist.png"]];
|
||||
[playlist2Item setIcon:[NSImage imageNamed:@"playlist.png"]];
|
||||
[playlist3Item setIcon:[NSImage imageNamed:@"playlist.png"]];
|
||||
|
||||
SourceListItem *playlistGroup = [SourceListItem itemWithTitle:@"Playlist Group" identifier:@"playlistgroup"];
|
||||
SourceListItem *playlistGroupItem = [SourceListItem itemWithTitle:@"Child Playlist" identifier:@"childplaylist"];
|
||||
PXSourceListItem *playlistGroup = [PXSourceListItem itemWithTitle:@"Playlist Group" identifier:@"playlistgroup"];
|
||||
PXSourceListItem *playlistGroupItem = [PXSourceListItem itemWithTitle:@"Child Playlist" identifier:@"childplaylist"];
|
||||
[playlistGroup setIcon:[NSImage imageNamed:@"playlistFolder.png"]];
|
||||
[playlistGroupItem setIcon:[NSImage imageNamed:@"playlist.png"]];
|
||||
[playlistGroup setChildren:[NSArray arrayWithObject:playlistGroupItem]];
|
||||
@@ -54,18 +63,12 @@
|
||||
[playlistsItem setChildren:[NSArray arrayWithObjects:playlist1Item, playlistGroup,playlist2Item,
|
||||
playlist3Item, nil]];
|
||||
|
||||
[sourceListItems addObject:libraryItem];
|
||||
[sourceListItems addObject:playlistsItem];
|
||||
[self.sourceListItems addObject:libraryItem];
|
||||
[self.sourceListItems addObject:playlistsItem];
|
||||
|
||||
[sourceList reloadData];
|
||||
[self.sourceList reloadData];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[sourceListItems release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Source List Data Source Methods
|
||||
@@ -74,7 +77,7 @@
|
||||
{
|
||||
//Works the same way as the NSOutlineView data source: `nil` means a parent item
|
||||
if(item==nil) {
|
||||
return [sourceListItems count];
|
||||
return [self.sourceListItems count];
|
||||
}
|
||||
else {
|
||||
return [[item children] count];
|
||||
@@ -86,7 +89,7 @@
|
||||
{
|
||||
//Works the same way as the NSOutlineView data source: `nil` means a parent item
|
||||
if(item==nil) {
|
||||
return [sourceListItems objectAtIndex:index];
|
||||
return [self.sourceListItems objectAtIndex:index];
|
||||
}
|
||||
else {
|
||||
return [[item children] objectAtIndex:index];
|
||||
@@ -114,19 +117,19 @@
|
||||
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList itemHasBadge:(id)item
|
||||
{
|
||||
return [item hasBadge];
|
||||
return !![(PXSourceListItem *)item badgeValue];
|
||||
}
|
||||
|
||||
|
||||
- (NSInteger)sourceList:(PXSourceList*)aSourceList badgeValueForItem:(id)item
|
||||
{
|
||||
return [item badgeValue];
|
||||
return [(PXSourceListItem *)item badgeValue].integerValue;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList itemHasIcon:(id)item
|
||||
{
|
||||
return [item hasIcon];
|
||||
return !![item icon];
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +147,7 @@
|
||||
} else {
|
||||
[m addItemWithTitle:@"clicked outside" action:nil keyEquivalent:@""];
|
||||
}
|
||||
return [m autorelease];
|
||||
return m;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
@@ -163,18 +166,18 @@
|
||||
|
||||
- (void)sourceListSelectionDidChange:(NSNotification *)notification
|
||||
{
|
||||
NSIndexSet *selectedIndexes = [sourceList selectedRowIndexes];
|
||||
NSIndexSet *selectedIndexes = [self.sourceList selectedRowIndexes];
|
||||
|
||||
//Set the label text to represent the new selection
|
||||
if([selectedIndexes count]>1)
|
||||
[selectedItemLabel setStringValue:@"(multiple)"];
|
||||
[self.selectedItemLabel setStringValue:@"(multiple)"];
|
||||
else if([selectedIndexes count]==1) {
|
||||
NSString *identifier = [[sourceList itemAtRow:[selectedIndexes firstIndex]] identifier];
|
||||
NSString *identifier = [[self.sourceList itemAtRow:[selectedIndexes firstIndex]] identifier];
|
||||
|
||||
[selectedItemLabel setStringValue:identifier];
|
||||
[self.selectedItemLabel setStringValue:identifier];
|
||||
}
|
||||
else {
|
||||
[selectedItemLabel setStringValue:@"(none)"];
|
||||
[self.selectedItemLabel setStringValue:@"(none)"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>uk.co.alexrozanski.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<string>com.alexrozanski.CellBased.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
|
Before Width: | Height: | Size: 415 B After Width: | Height: | Size: 415 B |
|
Before Width: | Height: | Size: 654 B After Width: | Height: | Size: 654 B |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 721 B |
|
Before Width: | Height: | Size: 671 B After Width: | Height: | Size: 671 B |
|
Before Width: | Height: | Size: 511 B After Width: | Height: | Size: 511 B |
|
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 702 B |
@@ -0,0 +1,688 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment version="1050" defaultVersion="1070" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application"/>
|
||||
<customObject id="373" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="29">
|
||||
<items>
|
||||
<menuItem title="New Application" id="56">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="New Application" systemMenu="apple" id="57">
|
||||
<items>
|
||||
<menuItem title="About New Application" id="58">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="236"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
|
||||
<menuItem isSeparatorItem="YES" id="143"/>
|
||||
<menuItem title="Services" id="131">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="130"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="144"/>
|
||||
<menuItem title="Hide New Application" keyEquivalent="h" id="134">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" id="369"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="145">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="-1" id="370"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="150">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="372"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="149"/>
|
||||
<menuItem title="Quit New Application" keyEquivalent="q" id="136">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-2" id="448"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="83">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="81">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="82"/>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="72"/>
|
||||
<menuItem title="Open Recent" id="124">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="126">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="127"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="79"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="73">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="193"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save" keyEquivalent="s" id="75">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="362"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="80">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="-1" id="363"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" id="112">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="74"/>
|
||||
<menuItem title="Page Setup..." keyEquivalent="P" id="77">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="87"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="78">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="86"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="684">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="685">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="686">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="749"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="687">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="745"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="688"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="689">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="741"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="690">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="755"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="691">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="742"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="692">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="754"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="693">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="756"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="694">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="758"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="695"/>
|
||||
<menuItem title="Find" id="696">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="734">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="735">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="772"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="736">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="775"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="737">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="771"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="738">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="773"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="739">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="774"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="697">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="727">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="728">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="752"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="729">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="753"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="730"/>
|
||||
<menuItem title="Check Spelling While Typing" id="731">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="747"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="732">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="750"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="733">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="698">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="718">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="719">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="720"/>
|
||||
<menuItem title="Smart Copy/Paste" id="721">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="743"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="722">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="744"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="723">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="724">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="762"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="725">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="726">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="699">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="714">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="715">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="716">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="717">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="700">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="711">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="712">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="751"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="713">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="759"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Format" id="375">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Format" id="376">
|
||||
<items>
|
||||
<menuItem title="Font" id="377">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="388">
|
||||
<items>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="389">
|
||||
<connections>
|
||||
<action selector="orderFrontFontPanel:" target="373" id="423"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="373" id="420"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="373" id="421"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="392">
|
||||
<connections>
|
||||
<action selector="underline:" target="-1" id="431"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="393"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="394">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="373" id="424"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="373" id="422"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="396"/>
|
||||
<menuItem title="Kern" id="397">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Kern" id="415">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="416">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardKerning:" target="-1" id="437"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="417">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffKerning:" target="-1" id="440"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Tighten" id="418">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="tightenKerning:" target="-1" id="430"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Loosen" id="419">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="loosenKerning:" target="-1" id="434"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Ligature" id="398">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Ligature" id="411">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="412">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardLigatures:" target="-1" id="438"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="413">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffLigatures:" target="-1" id="439"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use All" id="414">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useAllLigatures:" target="-1" id="433"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Baseline" id="399">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Baseline" id="405">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="406">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unscript:" target="-1" id="436"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Superscript" id="407">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="superscript:" target="-1" id="429"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Subscript" id="408">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="subscript:" target="-1" id="428"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Raise" id="409">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="raiseBaseline:" target="-1" id="425"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Lower" id="410">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowerBaseline:" target="-1" id="426"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="400"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="401">
|
||||
<connections>
|
||||
<action selector="orderFrontColorPanel:" target="-1" id="432"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="402"/>
|
||||
<menuItem title="Copy Style" keyEquivalent="c" id="403">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyFont:" target="-1" id="427"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Style" keyEquivalent="v" id="404">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteFont:" target="-1" id="435"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Text" id="776">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Text" id="777">
|
||||
<items>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="778">
|
||||
<connections>
|
||||
<action selector="alignLeft:" target="-1" id="804"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Center" keyEquivalent="|" id="779">
|
||||
<connections>
|
||||
<action selector="alignCenter:" target="-1" id="800"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Justify" id="780">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="alignJustified:" target="-1" id="802"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="781">
|
||||
<connections>
|
||||
<action selector="alignRight:" target="-1" id="803"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="782"/>
|
||||
<menuItem title="Writing Direction" id="783">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Writing Direction" id="788">
|
||||
<items>
|
||||
<menuItem title="Paragraph" enabled="NO" id="789">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="790">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="791">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="792">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="793"/>
|
||||
<menuItem title="Selection" enabled="NO" id="794">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="795">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="796">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="797">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="784"/>
|
||||
<menuItem title="Show Ruler" id="785">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleRuler:" target="-1" id="798"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="786">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyRuler:" target="-1" id="801"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="787">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteRuler:" target="-1" id="799"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="295">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="296">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="297">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="366"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="298">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="19">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="24">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="23">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="37"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="239">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="240"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="92"/>
|
||||
<menuItem title="Bring All to Front" id="5">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="39"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="103">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="106">
|
||||
<items>
|
||||
<menuItem title="New Application Help" keyEquivalent="?" id="111">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="360"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<window title="Cell-Based Source List Example" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" animationBehavior="default" id="367">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="53" y="204" width="853" height="570"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<view key="contentView" id="368">
|
||||
<rect key="frame" x="0.0" y="0.0" width="853" height="570"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="20" horizontalPageScroll="10" verticalLineScroll="20" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="811">
|
||||
<rect key="frame" x="0.0" y="0.0" width="214" height="570"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" heightSizable="YES"/>
|
||||
<clipView key="contentView" id="Ne8-cz-zNj">
|
||||
<rect key="frame" x="1" y="1" width="212" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" autosaveColumns="NO" rowHeight="20" indentationPerLevel="14" outlineTableColumn="816" id="814" customClass="PXSourceList">
|
||||
<rect key="frame" x="0.0" y="0.0" width="212" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="0.0"/>
|
||||
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn width="209" minWidth="16" maxWidth="1000" id="816">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" white="0.33333299" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="819">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="820" id="824"/>
|
||||
<outlet property="delegate" destination="820" id="823"/>
|
||||
</connections>
|
||||
</outlineView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="813">
|
||||
<rect key="frame" x="-100" y="-100" width="212" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="812">
|
||||
<rect key="frame" x="-100" y="-100" width="15" height="539"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<textField verticalHuggingPriority="750" id="830">
|
||||
<rect key="frame" x="361" y="277" width="195" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="The currently selected item is:" id="831">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" id="832">
|
||||
<rect key="frame" x="558" y="277" width="252" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" id="833">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
</window>
|
||||
<customObject id="820" customClass="AppDelegate">
|
||||
<connections>
|
||||
<outlet property="selectedItemLabel" destination="832" id="835"/>
|
||||
<outlet property="sourceList" destination="814" id="825"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
After Width: | Height: | Size: 70 KiB |
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// ViewBasedSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 28/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "PXSourceList.h"
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate, PXSourceListDataSource, PXSourceListDelegate>
|
||||
|
||||
@property (assign) IBOutlet NSWindow *window;
|
||||
@property (assign) IBOutlet PXSourceList *sourceList;
|
||||
@property (assign) IBOutlet NSButton *removeButton;
|
||||
@property (weak, nonatomic) IBOutlet NSTextField *selectedItemLabel;
|
||||
|
||||
- (IBAction)addButtonAction:(id)sender;
|
||||
- (IBAction)removeButtonAction:(id)sender;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,296 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// ViewBasedSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 28/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "Photo.h"
|
||||
#import "PhotoCollection.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
@property (strong, nonatomic) NSMutableArray *modelObjects;
|
||||
@property (strong, nonatomic) NSMutableArray *sourceListItems;
|
||||
@end
|
||||
|
||||
static NSString * const draggingType = @"SourceListExampleDraggingType";
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
// Used to support drag and drop in the source list.
|
||||
[self.sourceList registerForDraggedTypes:@[draggingType]];
|
||||
|
||||
self.sourceListItems = [[NSMutableArray alloc] init];
|
||||
[self setUpDataModel];
|
||||
|
||||
[self.sourceList reloadData];
|
||||
}
|
||||
|
||||
#pragma mark - Data Model
|
||||
|
||||
/* We could set an identifier on the PXSourceListItem instances, but it makes more sense to put our
|
||||
identifying information on the underlying model object in this case.
|
||||
|
||||
We also add some dummy Photo objects to each collection to emulate how a real model class would work.
|
||||
*/
|
||||
- (void)setUpDataModel
|
||||
{
|
||||
PhotoCollection *photosCollection = [PhotoCollection collectionWithTitle:@"Photos" identifier:@"photos" type:PhotoCollectionTypeLibrary];
|
||||
[self addNumberOfPhotoObjects:264 toCollection:photosCollection];
|
||||
|
||||
PhotoCollection *eventsCollection = [PhotoCollection collectionWithTitle:@"Events" identifier:@"events" type:PhotoCollectionTypeLibrary];
|
||||
[self addNumberOfPhotoObjects:689 toCollection:eventsCollection];
|
||||
|
||||
PhotoCollection *peopleCollection = [PhotoCollection collectionWithTitle:@"People" identifier:@"people" type:PhotoCollectionTypeLibrary];
|
||||
[self addNumberOfPhotoObjects:135 toCollection:peopleCollection];
|
||||
|
||||
PhotoCollection *placesCollection = [PhotoCollection collectionWithTitle:@"Places" identifier:@"places" type:PhotoCollectionTypeLibrary];
|
||||
[self addNumberOfPhotoObjects:28 toCollection:placesCollection];
|
||||
|
||||
PhotoCollection *snapsCollection = [PhotoCollection collectionWithTitle:@"Holiday Snaps" identifier:nil type:PhotoCollectionTypeUserCreated];
|
||||
[self addNumberOfPhotoObjects:40 toCollection:snapsCollection];
|
||||
|
||||
PhotoCollection *graduationCollection = [PhotoCollection collectionWithTitle:@"Graduation" identifier: nil type:PhotoCollectionTypeUserCreated];
|
||||
[self addNumberOfPhotoObjects:1050 toCollection:graduationCollection];
|
||||
|
||||
// Store all of the model objects in an array because each source list item only holds a weak reference to them.
|
||||
self.modelObjects = [@[photosCollection, eventsCollection, peopleCollection, placesCollection, snapsCollection, graduationCollection] mutableCopy];
|
||||
|
||||
// Icon images we're going to use in the Source List.
|
||||
NSImage *photosImage = [NSImage imageNamed:@"photos"];
|
||||
[photosImage setTemplate:YES];
|
||||
NSImage *eventsImage = [NSImage imageNamed:@"events"];
|
||||
[eventsImage setTemplate:YES];
|
||||
NSImage *peopleImage = [NSImage imageNamed:@"people"];
|
||||
[peopleImage setTemplate:YES];
|
||||
NSImage *placesImage = [NSImage imageNamed:@"places"];
|
||||
[placesImage setTemplate:YES];
|
||||
NSImage *albumImage = [NSImage imageNamed:@"album"];
|
||||
[albumImage setTemplate:YES];
|
||||
|
||||
// Set up our Source List data model used in the Source List data source methods.
|
||||
PXSourceListItem *libraryItem = [PXSourceListItem itemWithTitle:@"LIBRARY" identifier:nil];
|
||||
libraryItem.children = @[[PXSourceListItem itemWithRepresentedObject:photosCollection icon:photosImage],
|
||||
[PXSourceListItem itemWithRepresentedObject:eventsCollection icon:eventsImage],
|
||||
[PXSourceListItem itemWithRepresentedObject:peopleCollection icon:peopleImage],
|
||||
[PXSourceListItem itemWithRepresentedObject:placesCollection icon:placesImage]];
|
||||
|
||||
PXSourceListItem *albumsItem = [PXSourceListItem itemWithTitle:@"ALBUMS" identifier:nil];
|
||||
for (PhotoCollection *collection in @[snapsCollection, graduationCollection]) {
|
||||
[albumsItem addChildItem:[PXSourceListItem itemWithRepresentedObject:collection icon:albumImage]];
|
||||
}
|
||||
|
||||
[self.sourceListItems addObject:libraryItem];
|
||||
[self.sourceListItems addObject:albumsItem];
|
||||
}
|
||||
|
||||
/* Convenience method for adding dummy Photo objects to a PhotoCollection instance. */
|
||||
- (void)addNumberOfPhotoObjects:(NSUInteger)numberOfObjects toCollection:(PhotoCollection *)collection
|
||||
{
|
||||
NSMutableArray *photos = [[NSMutableArray alloc] init];
|
||||
for (NSUInteger i = 0; i < numberOfObjects; ++i)
|
||||
[photos addObject:[[Photo alloc] init]];
|
||||
collection.photos = photos;
|
||||
}
|
||||
|
||||
// Methods to avoid hardcoding subscripts into multiple places in the code.
|
||||
- (PXSourceListItem *)libraryItem
|
||||
{
|
||||
return self.sourceListItems[0];
|
||||
}
|
||||
|
||||
- (PXSourceListItem *)albumsItem
|
||||
{
|
||||
return self.sourceListItems[1];
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)addButtonAction:(id)sender
|
||||
{
|
||||
NSImage *albumImage = [NSImage imageNamed:@"album"];
|
||||
[albumImage setTemplate:YES];
|
||||
|
||||
PXSourceListItem *newItem = [PXSourceListItem itemWithTitle:@"New Album" identifier:nil icon:albumImage];
|
||||
[self.albumsItem addChildItem:newItem];
|
||||
|
||||
NSUInteger childIndex = [[self.albumsItem children] indexOfObject:newItem];
|
||||
[self.sourceList insertItemsAtIndexes:[NSIndexSet indexSetWithIndex:childIndex]
|
||||
inParent:self.albumsItem
|
||||
withAnimation:NSTableViewAnimationEffectNone];
|
||||
|
||||
[self.sourceList editColumn:0 row:[self.sourceList rowForItem:newItem] withEvent:nil select:YES];
|
||||
}
|
||||
|
||||
- (IBAction)removeButtonAction:(id)sender
|
||||
{
|
||||
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];
|
||||
|
||||
// Only 'album' items can be deleted.
|
||||
[parentItem removeChildItem:selectedItem];
|
||||
}
|
||||
|
||||
#pragma mark - PXSourceList Data Source
|
||||
|
||||
- (NSUInteger)sourceList:(PXSourceList*)sourceList numberOfChildrenOfItem:(id)item
|
||||
{
|
||||
if (!item)
|
||||
return self.sourceListItems.count;
|
||||
|
||||
return [[item children] count];
|
||||
}
|
||||
|
||||
- (id)sourceList:(PXSourceList*)aSourceList child:(NSUInteger)index ofItem:(id)item
|
||||
{
|
||||
if (!item)
|
||||
return self.sourceListItems[index];
|
||||
|
||||
return [[item children] objectAtIndex:index];
|
||||
}
|
||||
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList isItemExpandable:(id)item
|
||||
{
|
||||
return [item hasChildren];
|
||||
}
|
||||
|
||||
#pragma mark - PXSourceList Delegate
|
||||
|
||||
- (BOOL)sourceList:(PXSourceList *)aSourceList isGroupAlwaysExpanded:(id)group
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSView *)sourceList:(PXSourceList *)aSourceList viewForItem:(id)item
|
||||
{
|
||||
PXSourceListTableCellView *cellView = nil;
|
||||
if ([aSourceList levelForItem:item] == 0)
|
||||
cellView = [aSourceList makeViewWithIdentifier:@"HeaderCell" owner:nil];
|
||||
else
|
||||
cellView = [aSourceList makeViewWithIdentifier:@"MainCell" owner:nil];
|
||||
|
||||
PXSourceListItem *sourceListItem = item;
|
||||
PhotoCollection *collection = sourceListItem.representedObject;
|
||||
|
||||
// Only allow us to edit the user created photo collection titles.
|
||||
BOOL isTitleEditable = [collection isKindOfClass:[PhotoCollection class]] && collection.type == PhotoCollectionTypeUserCreated;
|
||||
cellView.textField.editable = isTitleEditable;
|
||||
cellView.textField.selectable = isTitleEditable;
|
||||
|
||||
cellView.textField.stringValue = sourceListItem.title ? sourceListItem.title : [sourceListItem.representedObject title];
|
||||
cellView.imageView.image = [item icon];
|
||||
cellView.badgeView.hidden = collection.photos.count == 0;
|
||||
cellView.badgeView.badgeValue = collection.photos.count;
|
||||
|
||||
return cellView;
|
||||
}
|
||||
|
||||
- (void)sourceListSelectionDidChange:(NSNotification *)notification
|
||||
{
|
||||
PXSourceListItem *selectedItem = [self.sourceList itemAtRow:self.sourceList.selectedRow];
|
||||
BOOL removeButtonEnabled = NO;
|
||||
NSString *newLabel = @"";
|
||||
if (selectedItem) {
|
||||
// Only allow us to remove items in the 'albums' group.
|
||||
removeButtonEnabled = [[self.albumsItem children] containsObject:selectedItem];
|
||||
|
||||
// We can use the underlying model object to do something based on the selection.
|
||||
PhotoCollection *collection = selectedItem.representedObject;
|
||||
|
||||
if (collection.identifier)
|
||||
newLabel = [NSString stringWithFormat:@"'%@' collection selected.", collection.identifier];
|
||||
else
|
||||
newLabel = @"User-created collection selected.";
|
||||
}
|
||||
|
||||
self.selectedItemLabel.stringValue = newLabel;
|
||||
self.removeButton.enabled = removeButtonEnabled;
|
||||
}
|
||||
|
||||
#pragma mark - Drag and Drop
|
||||
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
|
||||
{
|
||||
// Only allow user-created items (not those in "Library" to be moved around).
|
||||
for (PXSourceListItem *item in items) {
|
||||
PhotoCollection *collection = item.representedObject;
|
||||
if (![collection isKindOfClass:[PhotoCollection class]] || collection.type != PhotoCollectionTypeUserCreated)
|
||||
return NO;
|
||||
}
|
||||
|
||||
// We're dragging from and to the 'Albums' group.
|
||||
PXSourceListItem *parentItem = self.albumsItem;
|
||||
|
||||
// For simplicity in this example, put the dragged indexes on the pasteboard. Since we use the representedObject
|
||||
// on SourceListItem, we cannot reliably archive it directly.
|
||||
NSMutableIndexSet *draggedChildIndexes = [NSMutableIndexSet indexSet];
|
||||
for (PXSourceListItem *item in items)
|
||||
[draggedChildIndexes addIndex:[[parentItem children] indexOfObject:item]];
|
||||
|
||||
[pboard declareTypes:@[draggingType] owner:self];
|
||||
[pboard setData:[NSKeyedArchiver archivedDataWithRootObject:draggedChildIndexes] forType:draggingType];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSDragOperation)sourceList:(PXSourceList*)sourceList validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
|
||||
{
|
||||
PXSourceListItem *albumsItem = self.albumsItem;
|
||||
|
||||
// Only allow the items in the 'albums' group to be moved around. It can either be dropped on the group header, or inserted between other child items.
|
||||
// It can't be made the child of another item in this group, so the only valid case is when the proposedItem is the 'Albums' group item.
|
||||
if (![item isEqual:albumsItem])
|
||||
return NSDragOperationNone;
|
||||
|
||||
return NSDragOperationMove;
|
||||
}
|
||||
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index
|
||||
{
|
||||
NSPasteboard *draggingPasteboard = info.draggingPasteboard;
|
||||
NSMutableIndexSet *draggedChildIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:[draggingPasteboard dataForType:draggingType]];
|
||||
|
||||
PXSourceListItem *parentItem = self.albumsItem;
|
||||
NSMutableArray *draggedItems = [NSMutableArray array];
|
||||
[draggedChildIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
|
||||
[draggedItems addObject:[[parentItem children] objectAtIndex:idx]];
|
||||
}];
|
||||
|
||||
// An index of -1 means it's been dropped on the group header itself, so insert at the end of the group.
|
||||
if (index == -1)
|
||||
index = parentItem.children.count;
|
||||
|
||||
// Perform the Source List and model updates.
|
||||
[aSourceList beginUpdates];
|
||||
[aSourceList removeItemsAtIndexes:draggedChildIndexes
|
||||
inParent:parentItem
|
||||
withAnimation:NSTableViewAnimationEffectNone];
|
||||
[parentItem removeChildItems:draggedItems];
|
||||
|
||||
// We have to calculate the new child index which we have to perform the drop at, since we've just removed items from the parent item which
|
||||
// may have come before the drop index.
|
||||
NSUInteger adjustedDropIndex = index - [draggedChildIndexes countOfIndexesInRange:NSMakeRange(0, index)];
|
||||
|
||||
// The insertion indexes are now simply from the adjusted drop index.
|
||||
NSIndexSet *insertionIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(adjustedDropIndex, draggedChildIndexes.count)];
|
||||
[parentItem insertChildItems:draggedItems atIndexes:insertionIndexes];
|
||||
|
||||
[aSourceList insertItemsAtIndexes:insertionIndexes
|
||||
inParent:parentItem
|
||||
withAnimation:NSTableViewAnimationEffectNone];
|
||||
[aSourceList endUpdates];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,865 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="494" id="495"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application"/>
|
||||
<menu title="AMainMenu" systemMenu="main" id="29">
|
||||
<items>
|
||||
<menuItem title="ViewBasedSourceList" id="56">
|
||||
<menu key="submenu" title="ViewBasedSourceList" systemMenu="apple" id="57">
|
||||
<items>
|
||||
<menuItem title="About ViewBasedSourceList" id="58">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="236">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
|
||||
<menuItem isSeparatorItem="YES" id="143">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Services" id="131">
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="130"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="144">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Hide ViewBasedSourceList" keyEquivalent="h" id="134">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" id="367"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="145">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="-1" id="368"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="150">
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="370"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="149">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Quit ViewBasedSourceList" keyEquivalent="q" id="136">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-3" id="449"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="83">
|
||||
<menu key="submenu" title="File" id="81">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="82">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="373"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="72">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="374"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="124">
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="126">
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="127"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="79">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Close" keyEquivalent="w" id="73">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="193"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="75">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="362"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" id="112">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="74">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Page Setup..." keyEquivalent="P" id="77">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="87"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="78">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="86"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="217">
|
||||
<menu key="submenu" title="Edit" id="205">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="207">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="223"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="215">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="231"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="206">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="199">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="228"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="197">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="224"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="203">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="226"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="485">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="486"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="202">
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="235"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="198">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="232"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="214">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Find" id="218">
|
||||
<menu key="submenu" title="Find" id="220">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="241"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="534">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="535"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="487"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="488"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="489"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="210">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="216">
|
||||
<menu key="submenu" title="Spelling and Grammar" id="200">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="230"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="201">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="225"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="453"/>
|
||||
<menuItem title="Check Spelling While Typing" id="219">
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="346">
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="347"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="454">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="456"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="348">
|
||||
<menu key="submenu" title="Substitutions" id="349">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="457">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="458"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="459"/>
|
||||
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="460">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="461"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="462">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="463"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="450">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="451">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="452">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="464"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="465">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="468"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="466">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="467"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="211">
|
||||
<menu key="submenu" title="Speech" id="212">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="196">
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="233"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="195">
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="227"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Format" id="375">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Format" id="376">
|
||||
<items>
|
||||
<menuItem title="Font" id="377">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="388">
|
||||
<items>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="389">
|
||||
<connections>
|
||||
<action selector="orderFrontFontPanel:" target="420" id="424"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="420" id="421"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="420" id="422"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="392">
|
||||
<connections>
|
||||
<action selector="underline:" target="-1" id="432"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="393"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="394">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="420" id="425"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="420" id="423"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="396"/>
|
||||
<menuItem title="Kern" id="397">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Kern" id="415">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="416">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardKerning:" target="-1" id="438"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="417">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffKerning:" target="-1" id="441"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Tighten" id="418">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="tightenKerning:" target="-1" id="431"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Loosen" id="419">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="loosenKerning:" target="-1" id="435"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Ligatures" id="398">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Ligatures" id="411">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="412">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardLigatures:" target="-1" id="439"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="413">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffLigatures:" target="-1" id="440"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use All" id="414">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useAllLigatures:" target="-1" id="434"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Baseline" id="399">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Baseline" id="405">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="406">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unscript:" target="-1" id="437"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Superscript" id="407">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="superscript:" target="-1" id="430"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Subscript" id="408">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="subscript:" target="-1" id="429"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Raise" id="409">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="raiseBaseline:" target="-1" id="426"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Lower" id="410">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowerBaseline:" target="-1" id="427"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="400"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="401">
|
||||
<connections>
|
||||
<action selector="orderFrontColorPanel:" target="-1" id="433"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="402"/>
|
||||
<menuItem title="Copy Style" keyEquivalent="c" id="403">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyFont:" target="-1" id="428"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Style" keyEquivalent="v" id="404">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteFont:" target="-1" id="436"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Text" id="496">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Text" id="497">
|
||||
<items>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="498">
|
||||
<connections>
|
||||
<action selector="alignLeft:" target="-1" id="524"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Center" keyEquivalent="|" id="499">
|
||||
<connections>
|
||||
<action selector="alignCenter:" target="-1" id="518"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Justify" id="500">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="alignJustified:" target="-1" id="523"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="501">
|
||||
<connections>
|
||||
<action selector="alignRight:" target="-1" id="521"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="502"/>
|
||||
<menuItem title="Writing Direction" id="503">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Writing Direction" id="508">
|
||||
<items>
|
||||
<menuItem title="Paragraph" enabled="NO" id="509">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="510">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="525"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="511">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="526"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="512">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="527"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="513"/>
|
||||
<menuItem title="Selection" enabled="NO" id="514">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="515">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionNatural:" target="-1" id="528"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="516">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="529"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="517">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="530"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="504"/>
|
||||
<menuItem title="Show Ruler" id="505">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleRuler:" target="-1" id="520"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="506">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyRuler:" target="-1" id="522"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="507">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteRuler:" target="-1" id="519"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="295">
|
||||
<menu key="submenu" title="View" id="296">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="297">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="366"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="298">
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="19">
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="24">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="23">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="37"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="239">
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="240"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="92">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Bring All to Front" id="5">
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="39"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="490">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="491">
|
||||
<items>
|
||||
<menuItem title="ViewBasedSourceList Help" keyEquivalent="?" id="492">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="493"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<window title="View-Based Source List Example" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="707" height="453"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<view key="contentView" id="372">
|
||||
<rect key="frame" x="0.0" y="0.0" width="707" height="453"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<splitView dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="shf-dM-jNo">
|
||||
<rect key="frame" x="0.0" y="0.0" width="707" height="453"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<customView id="5z6-z4-Eis">
|
||||
<rect key="frame" x="0.0" y="0.0" width="192" height="453"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gyf-tN-jug">
|
||||
<rect key="frame" x="0.0" y="0.0" width="192" height="453"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" id="MeO-Mg-PDX">
|
||||
<rect key="frame" x="0.0" y="0.0" width="192" height="453"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" rowSizeStyle="systemDefault" viewBased="YES" indentationPerLevel="16" outlineTableColumn="KUf-Sx-qvM" id="6cp-sB-vmV" customClass="PXSourceList">
|
||||
<rect key="frame" x="0.0" y="0.0" width="192" height="453"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="0.0"/>
|
||||
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn identifier="AutomaticTableColumnIdentifier.0" width="189" minWidth="16" maxWidth="1000" id="KUf-Sx-qvM">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="III-Z6-nUC">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="HeaderCell" id="Bd4-M5-UeQ" customClass="PXSourceListTableCellView">
|
||||
<rect key="frame" x="1" y="0.0" width="189" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eai-EG-dRe">
|
||||
<rect key="frame" x="0.0" y="1" width="189" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="HEADER CELL" id="5xY-Iv-ixB">
|
||||
<font key="font" metaFont="smallSystemBold"/>
|
||||
<color key="textColor" red="0.43921568630000002" green="0.4941176471" blue="0.54901960780000003" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outlet property="textField" destination="eai-EG-dRe" id="6Az-Vc-kqF"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
<tableCellView identifier="MainCell" id="hLb-dC-CwP" customClass="PXSourceListTableCellView">
|
||||
<rect key="frame" x="1" y="17" width="189" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4ER-hQ-M6f">
|
||||
<rect key="frame" x="3" y="0.0" width="17" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="VxW-Wd-dQJ"/>
|
||||
</imageView>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GsV-wD-pbj">
|
||||
<rect key="frame" x="25" y="0.0" width="130" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="aO4-oB-jj3">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3Wj-Kn-7YJ" customClass="PXSourceListBadgeView">
|
||||
<rect key="frame" x="164" y="2" width="22" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="14" id="Lwo-5Q-Zmq"/>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="22" id="iAz-E3-9nO"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="3Wj-Kn-7YJ" secondAttribute="trailing" constant="3" id="4vE-ts-quP"/>
|
||||
<constraint firstAttribute="centerY" secondItem="3Wj-Kn-7YJ" secondAttribute="centerY" id="vSs-Ne-WPB"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="badgeView" destination="3Wj-Kn-7YJ" id="Tcs-WA-hkr"/>
|
||||
<outlet property="imageView" destination="4ER-hQ-M6f" id="le3-qL-W27"/>
|
||||
<outlet property="textField" destination="GsV-wD-pbj" id="yrR-Qw-aD4"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="494" id="F2A-gV-k7c"/>
|
||||
<outlet property="delegate" destination="494" id="G2w-lX-5Dl"/>
|
||||
</connections>
|
||||
</outlineView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="A8C-Fo-iI3">
|
||||
<rect key="frame" x="1" y="-15" width="0.0" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="63c-xj-Ig0">
|
||||
<rect key="frame" x="-15" y="1" width="16" height="0.0"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="BEV-Wz-OdK">
|
||||
<rect key="frame" x="1" y="2" width="30" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="30" id="BbI-az-zo0"/>
|
||||
<constraint firstAttribute="height" constant="21" id="OSH-IM-U1Y"/>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="30" id="Se2-9v-bwa"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="21" id="ZeV-jh-DKY"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSAddTemplate" imagePosition="overlaps" alignment="center" controlSize="mini" state="on" imageScaling="proportionallyDown" inset="2" id="ZO1-1M-bSI">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="addButtonAction:" target="494" id="Rqx-I4-1lq"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="iQU-Dr-qPa">
|
||||
<rect key="frame" x="28" y="2" width="30" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="30" id="52p-Vm-2Nb"/>
|
||||
<constraint firstAttribute="height" constant="21" id="ar8-y0-zCh"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" controlSize="mini" enabled="NO" state="on" imageScaling="proportionallyDown" inset="2" id="xbS-Ax-KfO">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="removeButtonAction:" target="494" id="F9K-WH-sD1"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Gyf-tN-jug" firstAttribute="leading" secondItem="5z6-z4-Eis" secondAttribute="leading" id="8on-dj-sEF"/>
|
||||
<constraint firstItem="BEV-Wz-OdK" firstAttribute="leading" secondItem="5z6-z4-Eis" secondAttribute="leading" constant="1" id="BRA-XD-2Sl"/>
|
||||
<constraint firstItem="iQU-Dr-qPa" firstAttribute="leading" secondItem="5z6-z4-Eis" secondAttribute="leading" constant="28" id="Ie2-h9-MID"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Gyf-tN-jug" secondAttribute="bottom" id="OVF-uf-K7N"/>
|
||||
<constraint firstAttribute="bottom" secondItem="BEV-Wz-OdK" secondAttribute="bottom" constant="2" id="VKt-iQ-iyA"/>
|
||||
<constraint firstAttribute="bottom" secondItem="iQU-Dr-qPa" secondAttribute="bottom" constant="2" id="ZJR-zF-U9n"/>
|
||||
<constraint firstItem="Gyf-tN-jug" firstAttribute="top" secondItem="5z6-z4-Eis" secondAttribute="top" id="e1F-no-bdo"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Gyf-tN-jug" secondAttribute="trailing" id="ipE-wL-Vti"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
<customView id="V5U-wh-2o3">
|
||||
<rect key="frame" x="193" y="0.0" width="514" height="453"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rTW-wK-rrG">
|
||||
<rect key="frame" x="18" y="212" width="478" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="474" id="7gl-Dw-sAL"/>
|
||||
<constraint firstAttribute="height" constant="30" id="V8l-Fv-qd6"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="DeD-wn-D0N">
|
||||
<font key="font" metaFont="system" size="25"/>
|
||||
<color key="textColor" white="0.33724908759124089" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="centerY" secondItem="rTW-wK-rrG" secondAttribute="centerY" id="H9N-qr-6zT"/>
|
||||
<constraint firstAttribute="centerX" secondItem="rTW-wK-rrG" secondAttribute="centerX" id="LAH-FJ-z3S"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</subviews>
|
||||
<holdingPriorities>
|
||||
<real value="250"/>
|
||||
<real value="250"/>
|
||||
</holdingPriorities>
|
||||
</splitView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="shf-dM-jNo" firstAttribute="leading" secondItem="372" secondAttribute="leading" id="57g-qe-uA7"/>
|
||||
<constraint firstAttribute="bottom" secondItem="shf-dM-jNo" secondAttribute="bottom" id="JzU-bz-Fxa"/>
|
||||
<constraint firstAttribute="trailing" secondItem="shf-dM-jNo" secondAttribute="trailing" id="WD2-Bb-YK5"/>
|
||||
<constraint firstItem="shf-dM-jNo" firstAttribute="top" secondItem="372" secondAttribute="top" id="zmB-td-zla"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</window>
|
||||
<customObject id="494" customClass="AppDelegate">
|
||||
<connections>
|
||||
<outlet property="removeButton" destination="iQU-Dr-qPa" id="MfB-vx-DLY"/>
|
||||
<outlet property="selectedItemLabel" destination="rTW-wK-rrG" id="GaD-A5-dDW"/>
|
||||
<outlet property="sourceList" destination="6cp-sB-vmV" id="0Ec-MJ-aU2"/>
|
||||
<outlet property="window" destination="371" id="532"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="420" customClass="NSFontManager"/>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSActionTemplate" width="14" height="14"/>
|
||||
<image name="NSAddTemplate" width="8" height="8"/>
|
||||
<image name="NSRemoveTemplate" width="8" height="8"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "32x32",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "32x32",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "128x128",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "128x128",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "256x256",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "256x256",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// Photo.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 27/01/2014.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/* A model class for illustration purposes that could be used for storing information about a photo. */
|
||||
@interface Photo : NSObject
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// Photo.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 27/01/2014.
|
||||
//
|
||||
//
|
||||
|
||||
#import "Photo.h"
|
||||
|
||||
@implementation Photo
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// PhotoCollection.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 06/01/2014.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(NSUInteger, PhotoCollectionType) {
|
||||
PhotoCollectionTypeLibrary,
|
||||
PhotoCollectionTypeUserCreated
|
||||
};
|
||||
|
||||
/* A simple example of a model class which is used by this project for storing information
|
||||
about a particular collection of objects in our sample library scenario. These objects
|
||||
are used by the SourceListItems to populate the Source List's content without having to
|
||||
synchronise the data (e.g. title) with each SourceListItem.
|
||||
*/
|
||||
@interface PhotoCollection : NSObject
|
||||
|
||||
@property (strong, nonatomic) NSString *title;
|
||||
@property (strong, nonatomic) NSString *identifier;
|
||||
@property (copy, nonatomic) NSArray *photos;
|
||||
@property (assign, nonatomic) PhotoCollectionType type;
|
||||
|
||||
+ (id)collectionWithTitle:(NSString *)title identifier:(NSString *)identifier type:(PhotoCollectionType)type;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// PhotoCollection.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 06/01/2014.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "PhotoCollection.h"
|
||||
|
||||
@implementation PhotoCollection
|
||||
|
||||
+ (id)collectionWithTitle:(NSString *)title identifier:(NSString *)identifier type:(PhotoCollectionType)type
|
||||
{
|
||||
PhotoCollection *collection = [[PhotoCollection alloc] init];
|
||||
|
||||
collection.title = title;
|
||||
collection.identifier = identifier;
|
||||
collection.type = type;
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
@end
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "18.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "63.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "14.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "3.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "20.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.alexrozanski.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Prefix header
|
||||
//
|
||||
// The contents of this file are implicitly included at the beginning of every source file.
|
||||
//
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw9840\paperh8400
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
|
||||
|
||||
\f0\b\fs24 \cf0 Engineering:
|
||||
\b0 \
|
||||
Some people\
|
||||
\
|
||||
|
||||
\b Human Interface Design:
|
||||
\b0 \
|
||||
Some other people\
|
||||
\
|
||||
|
||||
\b Testing:
|
||||
\b0 \
|
||||
Hopefully not nobody\
|
||||
\
|
||||
|
||||
\b Documentation:
|
||||
\b0 \
|
||||
Whoever\
|
||||
\
|
||||
|
||||
\b With special thanks to:
|
||||
\b0 \
|
||||
Mom\
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// main.m
|
||||
// ViewBasedSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 28/12/2013.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
PXSourceList is licensed under the New BSD License, as detailed below (adapted from OSI http://www.opensource.org/licenses/bsd-license.php):
|
||||
|
||||
Copyright © 2009-14, Alex Rozanski and other contributors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>uk.co.alexrozanski.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<string>com.alexrozanski.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
@@ -17,13 +17,13 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<string>2.0.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<string>2.0.2</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2012 Alex Rozanski. All rights reserved.</string>
|
||||
<string>Copyright © 2009-14 Alex Rozanski and other contributors. All rights reserved.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
@@ -0,0 +1,28 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'PXSourceList'
|
||||
s.version = '2.0.2'
|
||||
s.author = { 'Alex Rozanski' => 'alex@rozanski.me' }
|
||||
s.license = 'BSD'
|
||||
s.homepage = 'https://github.com/Perspx/PXSourceList'
|
||||
s.summary = 'A Source List control for OS X.'
|
||||
s.social_media_url = 'http://twitter.com/alexrozanski'
|
||||
s.requires_arc = true
|
||||
|
||||
s.description = <<-DESC
|
||||
PXSourceList is an NSOutlineView subclass which provides an easy-to-use
|
||||
implementation of a sidebar similar to that found in iTunes, iPhoto and
|
||||
Mail.app.
|
||||
|
||||
PXSourceList provides a simple API for displaying *icons* and *badges*
|
||||
which are often used in Source Lists. The project additionally contains
|
||||
and NSTableCellView subclass and generic data source model item for quick
|
||||
and easy setup.
|
||||
DESC
|
||||
|
||||
s.platform = :osx
|
||||
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_files = 'PXSourceList/**/*.{h,m}'
|
||||
end
|
||||
@@ -6,23 +6,58 @@
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
D251F6FD187342DA00FED7C9 /* Documentation */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = D251F6FE187342DB00FED7C9 /* Build configuration list for PBXAggregateTarget "Documentation" */;
|
||||
buildPhases = (
|
||||
D251F7011873439600FED7C9 /* ShellScript */,
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Documentation;
|
||||
productName = Documentation;
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
|
||||
D213027C14B9AFE200AAFF85 /* PXSourceList.h in Headers */ = {isa = PBXBuildFile; fileRef = D213027814B9AFE200AAFF85 /* PXSourceList.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D213027D14B9AFE200AAFF85 /* PXSourceList.m in Sources */ = {isa = PBXBuildFile; fileRef = D213027914B9AFE200AAFF85 /* PXSourceList.m */; };
|
||||
D213027E14B9AFE200AAFF85 /* PXSourceList.m in Sources */ = {isa = PBXBuildFile; fileRef = D213027914B9AFE200AAFF85 /* PXSourceList.m */; };
|
||||
D213027F14B9AFE200AAFF85 /* PXSourceListDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D213027A14B9AFE200AAFF85 /* PXSourceListDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D213028014B9AFE200AAFF85 /* PXSourceListDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = D213027B14B9AFE200AAFF85 /* PXSourceListDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D213028B14B9B01F00AAFF85 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D213028814B9B01F00AAFF85 /* AppDelegate.m */; };
|
||||
D213028C14B9B01F00AAFF85 /* SourceListItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D213028A14B9B01F00AAFF85 /* SourceListItem.m */; };
|
||||
D213028E14B9B02A00AAFF85 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D213028D14B9B02A00AAFF85 /* main.m */; };
|
||||
D21302BE14B9B24C00AAFF85 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D21302BD14B9B24C00AAFF85 /* MainMenu.xib */; };
|
||||
D21302C514B9B25700AAFF85 /* audiobooks.png in Resources */ = {isa = PBXBuildFile; fileRef = D21302BF14B9B25700AAFF85 /* audiobooks.png */; };
|
||||
D21302C614B9B25700AAFF85 /* movies.png in Resources */ = {isa = PBXBuildFile; fileRef = D21302C014B9B25700AAFF85 /* movies.png */; };
|
||||
D21302C714B9B25700AAFF85 /* music.png in Resources */ = {isa = PBXBuildFile; fileRef = D21302C114B9B25700AAFF85 /* music.png */; };
|
||||
D21302C814B9B25700AAFF85 /* playlist.png in Resources */ = {isa = PBXBuildFile; fileRef = D21302C214B9B25700AAFF85 /* playlist.png */; };
|
||||
D21302C914B9B25700AAFF85 /* playlistFolder.png in Resources */ = {isa = PBXBuildFile; fileRef = D21302C314B9B25700AAFF85 /* playlistFolder.png */; };
|
||||
D21302CA14B9B25700AAFF85 /* podcasts.png in Resources */ = {isa = PBXBuildFile; fileRef = D21302C414B9B25700AAFF85 /* podcasts.png */; };
|
||||
D21C59A0186EF8B200A8ECB3 /* PXSourceList.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC5EA2A12DC81ED001F282E /* PXSourceList.framework */; };
|
||||
D23A17591836AD790027F0D0 /* PXSourceListBadgeView.h in Headers */ = {isa = PBXBuildFile; fileRef = D23A17571836AD790027F0D0 /* PXSourceListBadgeView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D23A175B1836AD790027F0D0 /* PXSourceListBadgeView.m in Sources */ = {isa = PBXBuildFile; fileRef = D23A17581836AD790027F0D0 /* PXSourceListBadgeView.m */; };
|
||||
D23A175E1836AE280027F0D0 /* PXSourceListBadgeCell.h in Headers */ = {isa = PBXBuildFile; fileRef = D23A175C1836AE280027F0D0 /* PXSourceListBadgeCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D23A17601836AE280027F0D0 /* PXSourceListBadgeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D23A175D1836AE280027F0D0 /* PXSourceListBadgeCell.m */; };
|
||||
D24AE5531896A79700AC8CE0 /* Photo.m in Sources */ = {isa = PBXBuildFile; fileRef = D24AE5521896A79700AC8CE0 /* Photo.m */; };
|
||||
D24B88F7188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = D24B88F2188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.h */; };
|
||||
D24B88F8188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = D24B88F3188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.m */; };
|
||||
D24B88F9188EC3B100841497 /* PXSourceListPrivateConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = D24B88F4188EC3B100841497 /* PXSourceListPrivateConstants.h */; };
|
||||
D24B88FA188EC3B100841497 /* PXSourceListRuntimeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D24B88F5188EC3B100841497 /* PXSourceListRuntimeAdditions.h */; };
|
||||
D24B88FB188EC3B100841497 /* PXSourceListRuntimeAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D24B88F6188EC3B100841497 /* PXSourceListRuntimeAdditions.m */; };
|
||||
D24E1F02187DB323004DCBB0 /* PXSourceListItem.h in Headers */ = {isa = PBXBuildFile; fileRef = D24E1F00187DB323004DCBB0 /* PXSourceListItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D24E1F03187DB323004DCBB0 /* PXSourceListItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D24E1F01187DB323004DCBB0 /* PXSourceListItem.m */; };
|
||||
D251F6F5187317C000FED7C9 /* PXSourceListTableCellView.h in Headers */ = {isa = PBXBuildFile; fileRef = D251F6F3187317C000FED7C9 /* PXSourceListTableCellView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D251F6F6187317C000FED7C9 /* PXSourceListTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = D251F6F4187317C000FED7C9 /* PXSourceListTableCellView.m */; };
|
||||
D251F6FA1873240E00FED7C9 /* SourceListIcons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D251F6F91873240E00FED7C9 /* SourceListIcons.xcassets */; };
|
||||
D263123D186EF9F00036501C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D263123C186EF9F00036501C /* Cocoa.framework */; };
|
||||
D2631272186EFBBF0036501C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D2631271186EFBBF0036501C /* AppDelegate.m */; };
|
||||
D2631274186EFBC50036501C /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D2631273186EFBC50036501C /* MainMenu.xib */; };
|
||||
D263127B186EFBD20036501C /* audiobooks.png in Resources */ = {isa = PBXBuildFile; fileRef = D2631275186EFBD20036501C /* audiobooks.png */; };
|
||||
D263127C186EFBD20036501C /* movies.png in Resources */ = {isa = PBXBuildFile; fileRef = D2631276186EFBD20036501C /* movies.png */; };
|
||||
D263127D186EFBD20036501C /* music.png in Resources */ = {isa = PBXBuildFile; fileRef = D2631277186EFBD20036501C /* music.png */; };
|
||||
D263127E186EFBD20036501C /* playlist.png in Resources */ = {isa = PBXBuildFile; fileRef = D2631278186EFBD20036501C /* playlist.png */; };
|
||||
D263127F186EFBD20036501C /* playlistFolder.png in Resources */ = {isa = PBXBuildFile; fileRef = D2631279186EFBD20036501C /* playlistFolder.png */; };
|
||||
D2631280186EFBD20036501C /* podcasts.png in Resources */ = {isa = PBXBuildFile; fileRef = D263127A186EFBD20036501C /* podcasts.png */; };
|
||||
D2631282186EFBDC0036501C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D2631281186EFBDC0036501C /* main.m */; };
|
||||
D2631289186EFC4E0036501C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D2631288186EFC4E0036501C /* AppDelegate.m */; };
|
||||
D263128C186EFC5C0036501C /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D263128A186EFC5C0036501C /* MainMenu.xib */; };
|
||||
D263128E186EFC630036501C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D263128D186EFC630036501C /* Images.xcassets */; };
|
||||
D2631293186EFC830036501C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D2631292186EFC830036501C /* main.m */; };
|
||||
D2631299186EFD8E0036501C /* PXSourceList.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC5EA2A12DC81ED001F282E /* PXSourceList.framework */; };
|
||||
D2FF2953187AD32000CFEDD1 /* PhotoCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = D2FF2952187AD32000CFEDD1 /* PhotoCollection.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -33,6 +68,13 @@
|
||||
remoteGlobalIDString = 4CC5EA2912DC81ED001F282E;
|
||||
remoteInfo = PXSourceList;
|
||||
};
|
||||
D2631297186EFD8B0036501C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 4CC5EA2912DC81ED001F282E;
|
||||
remoteInfo = PXSourceList;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -47,23 +89,50 @@
|
||||
D213027914B9AFE200AAFF85 /* PXSourceList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PXSourceList.m; path = PXSourceList/PXSourceList.m; sourceTree = "<group>"; };
|
||||
D213027A14B9AFE200AAFF85 /* PXSourceListDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListDataSource.h; path = PXSourceList/PXSourceListDataSource.h; sourceTree = "<group>"; };
|
||||
D213027B14B9AFE200AAFF85 /* PXSourceListDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListDelegate.h; path = PXSourceList/PXSourceListDelegate.h; sourceTree = "<group>"; };
|
||||
D213028714B9B01F00AAFF85 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = "Demo Project/AppDelegate.h"; sourceTree = "<group>"; };
|
||||
D213028814B9B01F00AAFF85 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = "Demo Project/AppDelegate.m"; sourceTree = "<group>"; };
|
||||
D213028914B9B01F00AAFF85 /* SourceListItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceListItem.h; path = "Demo Project/SourceListItem.h"; sourceTree = "<group>"; };
|
||||
D213028A14B9B01F00AAFF85 /* SourceListItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SourceListItem.m; path = "Demo Project/SourceListItem.m"; sourceTree = "<group>"; };
|
||||
D213028D14B9B02A00AAFF85 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "Demo Project/main.m"; sourceTree = "<group>"; };
|
||||
D21302B614B9B16400AAFF85 /* PXSourceListDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "PXSourceListDemo-Info.plist"; path = "Demo Project/PXSourceListDemo-Info.plist"; sourceTree = "<group>"; };
|
||||
D21302B814B9B17200AAFF85 /* PXSourceList-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PXSourceList-Info.plist"; path = "PXSourceList/PXSourceList-Info.plist"; sourceTree = "<group>"; };
|
||||
D21302BC14B9B23700AAFF85 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = "Demo Project/English.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
D21302BD14B9B24C00AAFF85 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MainMenu.xib; path = "Demo Project/MainMenu.xib"; sourceTree = "<group>"; };
|
||||
D21302BF14B9B25700AAFF85 /* audiobooks.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = audiobooks.png; path = "Demo Project/Images/audiobooks.png"; sourceTree = "<group>"; };
|
||||
D21302C014B9B25700AAFF85 /* movies.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = movies.png; path = "Demo Project/Images/movies.png"; sourceTree = "<group>"; };
|
||||
D21302C114B9B25700AAFF85 /* music.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = music.png; path = "Demo Project/Images/music.png"; sourceTree = "<group>"; };
|
||||
D21302C214B9B25700AAFF85 /* playlist.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playlist.png; path = "Demo Project/Images/playlist.png"; sourceTree = "<group>"; };
|
||||
D21302C314B9B25700AAFF85 /* playlistFolder.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playlistFolder.png; path = "Demo Project/Images/playlistFolder.png"; sourceTree = "<group>"; };
|
||||
D21302C414B9B25700AAFF85 /* podcasts.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = podcasts.png; path = "Demo Project/Images/podcasts.png"; sourceTree = "<group>"; };
|
||||
D21302CB14B9B2FC00AAFF85 /* PXSourceListDemo_Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PXSourceListDemo_Prefix.pch; path = "Demo Project/PXSourceListDemo_Prefix.pch"; sourceTree = "<group>"; };
|
||||
D265C2D610E3814B00A1E824 /* TODO.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = TODO.rtf; sourceTree = "<group>"; };
|
||||
D23A17571836AD790027F0D0 /* PXSourceListBadgeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListBadgeView.h; path = PXSourceList/PXSourceListBadgeView.h; sourceTree = "<group>"; };
|
||||
D23A17581836AD790027F0D0 /* PXSourceListBadgeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PXSourceListBadgeView.m; path = PXSourceList/PXSourceListBadgeView.m; sourceTree = "<group>"; };
|
||||
D23A175C1836AE280027F0D0 /* PXSourceListBadgeCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListBadgeCell.h; path = PXSourceList/PXSourceListBadgeCell.h; sourceTree = "<group>"; };
|
||||
D23A175D1836AE280027F0D0 /* PXSourceListBadgeCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PXSourceListBadgeCell.m; path = PXSourceList/PXSourceListBadgeCell.m; sourceTree = "<group>"; };
|
||||
D24AE5511896A79700AC8CE0 /* Photo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Photo.h; path = Examples/ViewBasedSourceList/Photo.h; sourceTree = "<group>"; };
|
||||
D24AE5521896A79700AC8CE0 /* Photo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Photo.m; path = Examples/ViewBasedSourceList/Photo.m; sourceTree = "<group>"; };
|
||||
D24B88F2188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListDelegateDataSourceProxy.h; path = PXSourceList/Internal/PXSourceListDelegateDataSourceProxy.h; sourceTree = "<group>"; };
|
||||
D24B88F3188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PXSourceListDelegateDataSourceProxy.m; path = PXSourceList/Internal/PXSourceListDelegateDataSourceProxy.m; sourceTree = "<group>"; };
|
||||
D24B88F4188EC3B100841497 /* PXSourceListPrivateConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListPrivateConstants.h; path = PXSourceList/Internal/PXSourceListPrivateConstants.h; sourceTree = "<group>"; };
|
||||
D24B88F5188EC3B100841497 /* PXSourceListRuntimeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListRuntimeAdditions.h; path = PXSourceList/Internal/PXSourceListRuntimeAdditions.h; sourceTree = "<group>"; };
|
||||
D24B88F6188EC3B100841497 /* PXSourceListRuntimeAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PXSourceListRuntimeAdditions.m; path = PXSourceList/Internal/PXSourceListRuntimeAdditions.m; sourceTree = "<group>"; };
|
||||
D24E1F00187DB323004DCBB0 /* PXSourceListItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListItem.h; path = PXSourceList/PXSourceListItem.h; sourceTree = "<group>"; };
|
||||
D24E1F01187DB323004DCBB0 /* PXSourceListItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PXSourceListItem.m; path = PXSourceList/PXSourceListItem.m; sourceTree = "<group>"; };
|
||||
D251F6F3187317C000FED7C9 /* PXSourceListTableCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXSourceListTableCellView.h; path = PXSourceList/PXSourceListTableCellView.h; sourceTree = "<group>"; };
|
||||
D251F6F4187317C000FED7C9 /* PXSourceListTableCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PXSourceListTableCellView.m; path = PXSourceList/PXSourceListTableCellView.m; sourceTree = "<group>"; };
|
||||
D251F6F91873240E00FED7C9 /* SourceListIcons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = SourceListIcons.xcassets; path = Examples/ViewBasedSourceList/SourceListIcons.xcassets; sourceTree = "<group>"; };
|
||||
D263123B186EF9F00036501C /* ViewBasedSourceList.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ViewBasedSourceList.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D263123C186EF9F00036501C /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
D2631257186EF9F10036501C /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
|
||||
D2631270186EFBBF0036501C /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Examples/CellBasedSourceList/AppDelegate.h; sourceTree = "<group>"; };
|
||||
D2631271186EFBBF0036501C /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Examples/CellBasedSourceList/AppDelegate.m; sourceTree = "<group>"; };
|
||||
D2631273186EFBC50036501C /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MainMenu.xib; path = Examples/CellBasedSourceList/MainMenu.xib; sourceTree = "<group>"; };
|
||||
D2631275186EFBD20036501C /* audiobooks.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = audiobooks.png; path = Examples/CellBasedSourceList/Images/audiobooks.png; sourceTree = "<group>"; };
|
||||
D2631276186EFBD20036501C /* movies.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = movies.png; path = Examples/CellBasedSourceList/Images/movies.png; sourceTree = "<group>"; };
|
||||
D2631277186EFBD20036501C /* music.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = music.png; path = Examples/CellBasedSourceList/Images/music.png; sourceTree = "<group>"; };
|
||||
D2631278186EFBD20036501C /* playlist.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playlist.png; path = Examples/CellBasedSourceList/Images/playlist.png; sourceTree = "<group>"; };
|
||||
D2631279186EFBD20036501C /* playlistFolder.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playlistFolder.png; path = Examples/CellBasedSourceList/Images/playlistFolder.png; sourceTree = "<group>"; };
|
||||
D263127A186EFBD20036501C /* podcasts.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = podcasts.png; path = Examples/CellBasedSourceList/Images/podcasts.png; sourceTree = "<group>"; };
|
||||
D2631281186EFBDC0036501C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Examples/CellBasedSourceList/main.m; sourceTree = "<group>"; };
|
||||
D2631283186EFBE50036501C /* PXSourceListDemo_Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PXSourceListDemo_Prefix.pch; path = Examples/CellBasedSourceList/PXSourceListDemo_Prefix.pch; sourceTree = "<group>"; };
|
||||
D2631284186EFBEB0036501C /* PXSourceListDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PXSourceListDemo-Info.plist"; path = "Examples/CellBasedSourceList/PXSourceListDemo-Info.plist"; sourceTree = "<group>"; };
|
||||
D2631286186EFBFA0036501C /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = Examples/CellBasedSourceList/English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
D2631287186EFC4E0036501C /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Examples/ViewBasedSourceList/AppDelegate.h; sourceTree = "<group>"; };
|
||||
D2631288186EFC4E0036501C /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Examples/ViewBasedSourceList/AppDelegate.m; sourceTree = "<group>"; };
|
||||
D263128B186EFC5C0036501C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Examples/ViewBasedSourceList/Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
D263128D186EFC630036501C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Examples/ViewBasedSourceList/Images.xcassets; sourceTree = "<group>"; };
|
||||
D263128F186EFC6D0036501C /* ViewBasedSourceList-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "ViewBasedSourceList-Info.plist"; path = "Examples/ViewBasedSourceList/ViewBasedSourceList-Info.plist"; sourceTree = SOURCE_ROOT; };
|
||||
D2631291186EFC7C0036501C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Examples/ViewBasedSourceList/en.lproj/InfoPlist.strings; sourceTree = SOURCE_ROOT; };
|
||||
D2631292186EFC830036501C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Examples/ViewBasedSourceList/main.m; sourceTree = SOURCE_ROOT; };
|
||||
D2631294186EFC890036501C /* ViewBasedSourceList-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "ViewBasedSourceList-Prefix.pch"; path = "Examples/ViewBasedSourceList/ViewBasedSourceList-Prefix.pch"; sourceTree = SOURCE_ROOT; };
|
||||
D2631296186EFC910036501C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = Examples/ViewBasedSourceList/en.lproj/Credits.rtf; sourceTree = SOURCE_ROOT; };
|
||||
D2BA8D1A1891CB0500E4A15A /* PXSourceList-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PXSourceList-Info.plist"; sourceTree = "<group>"; };
|
||||
D2FF2951187AD32000CFEDD1 /* PhotoCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhotoCollection.h; path = Examples/ViewBasedSourceList/PhotoCollection.h; sourceTree = "<group>"; };
|
||||
D2FF2952187AD32000CFEDD1 /* PhotoCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PhotoCollection.m; path = Examples/ViewBasedSourceList/PhotoCollection.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -78,10 +147,20 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D21C59A0186EF8B200A8ECB3 /* PXSourceList.framework in Frameworks */,
|
||||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D2631238186EF9F00036501C /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D2631299186EFD8E0036501C /* PXSourceList.framework in Frameworks */,
|
||||
D263123D186EF9F00036501C /* Cocoa.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@@ -92,6 +171,15 @@
|
||||
D213027914B9AFE200AAFF85 /* PXSourceList.m */,
|
||||
D213027A14B9AFE200AAFF85 /* PXSourceListDataSource.h */,
|
||||
D213027B14B9AFE200AAFF85 /* PXSourceListDelegate.h */,
|
||||
D23A17571836AD790027F0D0 /* PXSourceListBadgeView.h */,
|
||||
D23A17581836AD790027F0D0 /* PXSourceListBadgeView.m */,
|
||||
D23A175C1836AE280027F0D0 /* PXSourceListBadgeCell.h */,
|
||||
D23A175D1836AE280027F0D0 /* PXSourceListBadgeCell.m */,
|
||||
D251F6F3187317C000FED7C9 /* PXSourceListTableCellView.h */,
|
||||
D251F6F4187317C000FED7C9 /* PXSourceListTableCellView.m */,
|
||||
D24E1F00187DB323004DCBB0 /* PXSourceListItem.h */,
|
||||
D24E1F01187DB323004DCBB0 /* PXSourceListItem.m */,
|
||||
D2CD7D4A186B02690003E038 /* Internal */,
|
||||
D21302BA14B9B1DC00AAFF85 /* Supporting Files */,
|
||||
);
|
||||
name = PXSourceList;
|
||||
@@ -120,6 +208,7 @@
|
||||
children = (
|
||||
8D1107320486CEB800E47090 /* PXSourceList.app */,
|
||||
4CC5EA2A12DC81ED001F282E /* PXSourceList.framework */,
|
||||
D263123B186EF9F00036501C /* ViewBasedSourceList.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -127,10 +216,9 @@
|
||||
29B97314FDCFA39411CA2CEA /* PXSourceList */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D265C2D610E3814B00A1E824 /* TODO.rtf */,
|
||||
D205EDDD10F7A1EE004C6545 /* README.markdown */,
|
||||
080E96DDFE201D6D7F000001 /* PXSourceList */,
|
||||
D213027714B9AFCA00AAFF85 /* Demo Project */,
|
||||
D213027714B9AFCA00AAFF85 /* Example Projects */,
|
||||
29B97323FDCFA39411CA2CEA /* Frameworks */,
|
||||
19C28FACFE9D520D11CA2CBB /* Products */,
|
||||
);
|
||||
@@ -140,10 +228,10 @@
|
||||
29B97315FDCFA39411CA2CEA /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D21302CB14B9B2FC00AAFF85 /* PXSourceListDemo_Prefix.pch */,
|
||||
D21302B614B9B16400AAFF85 /* PXSourceListDemo-Info.plist */,
|
||||
D21302BB14B9B23700AAFF85 /* InfoPlist.strings */,
|
||||
D213028D14B9B02A00AAFF85 /* main.m */,
|
||||
D2631281186EFBDC0036501C /* main.m */,
|
||||
D2631283186EFBE50036501C /* PXSourceListDemo_Prefix.pch */,
|
||||
D2631284186EFBEB0036501C /* PXSourceListDemo-Info.plist */,
|
||||
D2631285186EFBFA0036501C /* InfoPlist.strings */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
@@ -151,7 +239,7 @@
|
||||
29B97317FDCFA39411CA2CEA /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D21302BD14B9B24C00AAFF85 /* MainMenu.xib */,
|
||||
D2631273186EFBC50036501C /* MainMenu.xib */,
|
||||
D27B7D2710E0C925004D7DBC /* Icons */,
|
||||
);
|
||||
name = Resources;
|
||||
@@ -161,45 +249,104 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
|
||||
D263123C186EF9F00036501C /* Cocoa.framework */,
|
||||
D2631257186EF9F10036501C /* XCTest.framework */,
|
||||
1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D213027714B9AFCA00AAFF85 /* Demo Project */ = {
|
||||
D213027714B9AFCA00AAFF85 /* Example Projects */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D213028714B9B01F00AAFF85 /* AppDelegate.h */,
|
||||
D213028814B9B01F00AAFF85 /* AppDelegate.m */,
|
||||
D213028914B9B01F00AAFF85 /* SourceListItem.h */,
|
||||
D213028A14B9B01F00AAFF85 /* SourceListItem.m */,
|
||||
29B97317FDCFA39411CA2CEA /* Resources */,
|
||||
29B97315FDCFA39411CA2CEA /* Supporting Files */,
|
||||
D2631236186EF9CB0036501C /* View-based Source List */,
|
||||
D21C599D186EF84900A8ECB3 /* Cell-based Source List */,
|
||||
);
|
||||
name = "Demo Project";
|
||||
name = "Example Projects";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D21302BA14B9B1DC00AAFF85 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D21302B814B9B17200AAFF85 /* PXSourceList-Info.plist */,
|
||||
D2BA8D1A1891CB0500E4A15A /* PXSourceList-Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D21C599D186EF84900A8ECB3 /* Cell-based Source List */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2631270186EFBBF0036501C /* AppDelegate.h */,
|
||||
D2631271186EFBBF0036501C /* AppDelegate.m */,
|
||||
29B97317FDCFA39411CA2CEA /* Resources */,
|
||||
29B97315FDCFA39411CA2CEA /* Supporting Files */,
|
||||
);
|
||||
name = "Cell-based Source List";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D2631236186EF9CB0036501C /* View-based Source List */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2631287186EFC4E0036501C /* AppDelegate.h */,
|
||||
D2631288186EFC4E0036501C /* AppDelegate.m */,
|
||||
D263128A186EFC5C0036501C /* MainMenu.xib */,
|
||||
D263128D186EFC630036501C /* Images.xcassets */,
|
||||
D251F6F91873240E00FED7C9 /* SourceListIcons.xcassets */,
|
||||
D2FF2950187AD30200CFEDD1 /* Model */,
|
||||
D263123F186EF9F00036501C /* Supporting Files */,
|
||||
);
|
||||
name = "View-based Source List";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D263123F186EF9F00036501C /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D263128F186EFC6D0036501C /* ViewBasedSourceList-Info.plist */,
|
||||
D2631290186EFC7C0036501C /* InfoPlist.strings */,
|
||||
D2631292186EFC830036501C /* main.m */,
|
||||
D2631294186EFC890036501C /* ViewBasedSourceList-Prefix.pch */,
|
||||
D2631295186EFC910036501C /* Credits.rtf */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
path = ViewBasedSourceList;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D27B7D2710E0C925004D7DBC /* Icons */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D21302BF14B9B25700AAFF85 /* audiobooks.png */,
|
||||
D21302C014B9B25700AAFF85 /* movies.png */,
|
||||
D21302C114B9B25700AAFF85 /* music.png */,
|
||||
D21302C214B9B25700AAFF85 /* playlist.png */,
|
||||
D21302C314B9B25700AAFF85 /* playlistFolder.png */,
|
||||
D21302C414B9B25700AAFF85 /* podcasts.png */,
|
||||
D2631275186EFBD20036501C /* audiobooks.png */,
|
||||
D2631276186EFBD20036501C /* movies.png */,
|
||||
D2631277186EFBD20036501C /* music.png */,
|
||||
D2631278186EFBD20036501C /* playlist.png */,
|
||||
D2631279186EFBD20036501C /* playlistFolder.png */,
|
||||
D263127A186EFBD20036501C /* podcasts.png */,
|
||||
);
|
||||
name = Icons;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D2CD7D4A186B02690003E038 /* Internal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D24B88F4188EC3B100841497 /* PXSourceListPrivateConstants.h */,
|
||||
D24B88F2188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.h */,
|
||||
D24B88F3188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.m */,
|
||||
D24B88F5188EC3B100841497 /* PXSourceListRuntimeAdditions.h */,
|
||||
D24B88F6188EC3B100841497 /* PXSourceListRuntimeAdditions.m */,
|
||||
);
|
||||
name = Internal;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D2FF2950187AD30200CFEDD1 /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D24AE5511896A79700AC8CE0 /* Photo.h */,
|
||||
D24AE5521896A79700AC8CE0 /* Photo.m */,
|
||||
D2FF2951187AD32000CFEDD1 /* PhotoCollection.h */,
|
||||
D2FF2952187AD32000CFEDD1 /* PhotoCollection.m */,
|
||||
);
|
||||
name = Model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@@ -207,6 +354,13 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D24B88F7188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.h in Headers */,
|
||||
D24E1F02187DB323004DCBB0 /* PXSourceListItem.h in Headers */,
|
||||
D23A175E1836AE280027F0D0 /* PXSourceListBadgeCell.h in Headers */,
|
||||
D24B88FA188EC3B100841497 /* PXSourceListRuntimeAdditions.h in Headers */,
|
||||
D251F6F5187317C000FED7C9 /* PXSourceListTableCellView.h in Headers */,
|
||||
D24B88F9188EC3B100841497 /* PXSourceListPrivateConstants.h in Headers */,
|
||||
D23A17591836AD790027F0D0 /* PXSourceListBadgeView.h in Headers */,
|
||||
D213027C14B9AFE200AAFF85 /* PXSourceList.h in Headers */,
|
||||
D213027F14B9AFE200AAFF85 /* PXSourceListDataSource.h in Headers */,
|
||||
D213028014B9AFE200AAFF85 /* PXSourceListDelegate.h in Headers */,
|
||||
@@ -234,9 +388,9 @@
|
||||
productReference = 4CC5EA2A12DC81ED001F282E /* PXSourceList.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
8D1107260486CEB800E47090 /* PXSourceListDemo */ = {
|
||||
8D1107260486CEB800E47090 /* CellBasedSourceList */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "PXSourceListDemo" */;
|
||||
buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "CellBasedSourceList" */;
|
||||
buildPhases = (
|
||||
8D11072C0486CEB800E47090 /* Sources */,
|
||||
8D1107290486CEB800E47090 /* Resources */,
|
||||
@@ -247,19 +401,37 @@
|
||||
dependencies = (
|
||||
4CC5EA3012DC8209001F282E /* PBXTargetDependency */,
|
||||
);
|
||||
name = PXSourceListDemo;
|
||||
name = CellBasedSourceList;
|
||||
productInstallPath = "$(HOME)/Applications";
|
||||
productName = PXSourceList;
|
||||
productReference = 8D1107320486CEB800E47090 /* PXSourceList.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
D263123A186EF9F00036501C /* ViewBasedSourceList */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D2631264186EF9F10036501C /* Build configuration list for PBXNativeTarget "ViewBasedSourceList" */;
|
||||
buildPhases = (
|
||||
D2631237186EF9F00036501C /* Sources */,
|
||||
D2631238186EF9F00036501C /* Frameworks */,
|
||||
D2631239186EF9F00036501C /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D2631298186EFD8B0036501C /* PBXTargetDependency */,
|
||||
);
|
||||
name = ViewBasedSourceList;
|
||||
productName = ViewBasedSourceList;
|
||||
productReference = D263123B186EF9F00036501C /* ViewBasedSourceList.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0450;
|
||||
LastUpgradeCheck = 0500;
|
||||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "PXSourceList" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
@@ -270,13 +442,17 @@
|
||||
Japanese,
|
||||
French,
|
||||
German,
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 29B97314FDCFA39411CA2CEA /* PXSourceList */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
8D1107260486CEB800E47090 /* PXSourceListDemo */,
|
||||
8D1107260486CEB800E47090 /* CellBasedSourceList */,
|
||||
D263123A186EF9F00036501C /* ViewBasedSourceList */,
|
||||
4CC5EA2912DC81ED001F282E /* PXSourceList */,
|
||||
D251F6FD187342DA00FED7C9 /* Documentation */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -293,24 +469,56 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D21302BE14B9B24C00AAFF85 /* MainMenu.xib in Resources */,
|
||||
D21302C514B9B25700AAFF85 /* audiobooks.png in Resources */,
|
||||
D21302C614B9B25700AAFF85 /* movies.png in Resources */,
|
||||
D21302C714B9B25700AAFF85 /* music.png in Resources */,
|
||||
D21302C814B9B25700AAFF85 /* playlist.png in Resources */,
|
||||
D21302C914B9B25700AAFF85 /* playlistFolder.png in Resources */,
|
||||
D21302CA14B9B25700AAFF85 /* podcasts.png in Resources */,
|
||||
D2631274186EFBC50036501C /* MainMenu.xib in Resources */,
|
||||
D263127E186EFBD20036501C /* playlist.png in Resources */,
|
||||
D263127D186EFBD20036501C /* music.png in Resources */,
|
||||
D263127F186EFBD20036501C /* playlistFolder.png in Resources */,
|
||||
D2631280186EFBD20036501C /* podcasts.png in Resources */,
|
||||
D263127B186EFBD20036501C /* audiobooks.png in Resources */,
|
||||
D263127C186EFBD20036501C /* movies.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D2631239186EF9F00036501C /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D263128E186EFC630036501C /* Images.xcassets in Resources */,
|
||||
D251F6FA1873240E00FED7C9 /* SourceListIcons.xcassets in Resources */,
|
||||
D263128C186EFC5C0036501C /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
D251F7011873439600FED7C9 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Note: requires appledoc to be installed. See https://github.com/tomaz/appledoc for more information.\n\n# Thanks to http://stackoverflow.com/a/13871762/75245 for help with the parsing.\ninfoPlistLocation=${PROJECT_DIR}/`/usr/bin/xcrun xcodebuild -showBuildSettings -target \"PXSourceList\" 2>/dev/null | grep \"INFOPLIST_FILE\" | sed 's/[ ]*INFOPLIST_FILE = //'`\n\nversion=`/usr/libexec/Plistbuddy -c 'Print :CFBundleShortVersionString' $infoPlistLocation`\noutputPath=\"docs\"\nsourceDir=\"PXSourceList\"\n\n/usr/local/bin/appledoc \\\n--project-name \"${PROJECT_NAME}\" \\\n--project-company \"Alex Rozanski\" \\\n--project-version \"${version}\" \\\n--company-id \"com.alexrozanski\" \\\n--output \"${outputPath}\" \\\n--logformat \"xcode\" \\\n--no-repeat-first-par \\\n--keep-intermediate-files \\\n--no-install-docset \\\n--clean-output \\\n${sourceDir}";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
4CC5EA2712DC81ED001F282E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D23A17601836AE280027F0D0 /* PXSourceListBadgeCell.m in Sources */,
|
||||
D24E1F03187DB323004DCBB0 /* PXSourceListItem.m in Sources */,
|
||||
D24B88FB188EC3B100841497 /* PXSourceListRuntimeAdditions.m in Sources */,
|
||||
D23A175B1836AD790027F0D0 /* PXSourceListBadgeView.m in Sources */,
|
||||
D213027E14B9AFE200AAFF85 /* PXSourceList.m in Sources */,
|
||||
D251F6F6187317C000FED7C9 /* PXSourceListTableCellView.m in Sources */,
|
||||
D24B88F8188EC3B100841497 /* PXSourceListDelegateDataSourceProxy.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -318,10 +526,19 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D213027D14B9AFE200AAFF85 /* PXSourceList.m in Sources */,
|
||||
D213028B14B9B01F00AAFF85 /* AppDelegate.m in Sources */,
|
||||
D213028C14B9B01F00AAFF85 /* SourceListItem.m in Sources */,
|
||||
D213028E14B9B02A00AAFF85 /* main.m in Sources */,
|
||||
D2631282186EFBDC0036501C /* main.m in Sources */,
|
||||
D2631272186EFBBF0036501C /* AppDelegate.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D2631237186EF9F00036501C /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D24AE5531896A79700AC8CE0 /* Photo.m in Sources */,
|
||||
D2631293186EFC830036501C /* main.m in Sources */,
|
||||
D2631289186EFC4E0036501C /* AppDelegate.m in Sources */,
|
||||
D2FF2953187AD32000CFEDD1 /* PhotoCollection.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -333,17 +550,46 @@
|
||||
target = 4CC5EA2912DC81ED001F282E /* PXSourceList */;
|
||||
targetProxy = 4CC5EA2F12DC8209001F282E /* PBXContainerItemProxy */;
|
||||
};
|
||||
D2631298186EFD8B0036501C /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 4CC5EA2912DC81ED001F282E /* PXSourceList */;
|
||||
targetProxy = D2631297186EFD8B0036501C /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
D21302BB14B9B23700AAFF85 /* InfoPlist.strings */ = {
|
||||
D2631285186EFBFA0036501C /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
D21302BC14B9B23700AAFF85 /* English */,
|
||||
D2631286186EFBFA0036501C /* English */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D263128A186EFC5C0036501C /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
D263128B186EFC5C0036501C /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D2631290186EFC7C0036501C /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
D2631291186EFC7C0036501C /* en */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D2631295186EFC910036501C /* Credits.rtf */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
D2631296186EFC910036501C /* en */,
|
||||
);
|
||||
name = Credits.rtf;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
@@ -351,18 +597,19 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_GC = supported;
|
||||
GCC_ENABLE_OBJC_GC = unsupported;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
|
||||
INFOPLIST_FILE = "PXSourceList/PXSourceList-Info.plist";
|
||||
INFOPLIST_FILE = "PXSourceList-Info.plist";
|
||||
INSTALL_PATH = "@loader_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
OTHER_LDFLAGS = (
|
||||
@@ -380,17 +627,18 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_ENABLE_OBJC_GC = supported;
|
||||
GCC_ENABLE_OBJC_GC = unsupported;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
|
||||
INFOPLIST_FILE = "PXSourceList/PXSourceList-Info.plist";
|
||||
INFOPLIST_FILE = "PXSourceList-Info.plist";
|
||||
INSTALL_PATH = "@loader_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
OTHER_LDFLAGS = (
|
||||
@@ -409,18 +657,15 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/build/Debug\"",
|
||||
);
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Demo Project/PXSourceListDemo_Prefix.pch";
|
||||
INFOPLIST_FILE = "Demo Project/PXSourceListDemo-Info.plist";
|
||||
GCC_PREFIX_HEADER = Examples/CellBasedSourceList/CellBasedSourceList_Prefix.pch;
|
||||
INFOPLIST_FILE = "Examples/CellBasedSourceList/CellBasedSourceList-Info.plist";
|
||||
INSTALL_PATH = "$(HOME)/Applications";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
PRODUCT_NAME = PXSourceList;
|
||||
@@ -432,17 +677,14 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/build/Debug\"",
|
||||
);
|
||||
GCC_ENABLE_OBJC_GC = unsupported;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Demo Project/PXSourceListDemo_Prefix.pch";
|
||||
INFOPLIST_FILE = "Demo Project/PXSourceListDemo-Info.plist";
|
||||
GCC_PREFIX_HEADER = Examples/CellBasedSourceList/CellBasedSourceList_Prefix.pch;
|
||||
INFOPLIST_FILE = "Examples/CellBasedSourceList/CellBasedSourceList-Info.plist";
|
||||
INSTALL_PATH = "$(HOME)/Applications";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
PRODUCT_NAME = PXSourceList;
|
||||
@@ -453,11 +695,11 @@
|
||||
C01FCF4F08A954540054247B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
VALID_ARCHS = "i386 x86_64";
|
||||
@@ -467,15 +709,103 @@
|
||||
C01FCF5008A954540054247B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
SDKROOT = macosx;
|
||||
VALID_ARCHS = "i386 x86_64";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D251F6FF187342DB00FED7C9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D251F700187342DB00FED7C9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D2631265186EF9F10036501C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Examples/ViewBasedSourceList/ViewBasedSourceList-Prefix.pch";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = "Examples/ViewBasedSourceList/ViewBasedSourceList-Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D2631266186EF9F10036501C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Examples/ViewBasedSourceList/ViewBasedSourceList-Prefix.pch";
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = "Examples/ViewBasedSourceList/ViewBasedSourceList-Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@@ -488,7 +818,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "PXSourceListDemo" */ = {
|
||||
C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "CellBasedSourceList" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C01FCF4B08A954540054247B /* Debug */,
|
||||
@@ -506,6 +836,24 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D251F6FE187342DB00FED7C9 /* Build configuration list for PBXAggregateTarget "Documentation" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D251F6FF187342DB00FED7C9 /* Debug */,
|
||||
D251F700187342DB00FED7C9 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D2631264186EF9F10036501C /* Build configuration list for PBXNativeTarget "ViewBasedSourceList" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D2631265186EF9F10036501C /* Debug */,
|
||||
D2631266186EF9F10036501C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// PXSourceListDelegateDataSourceProxy.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 25/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "PXSourceList.h"
|
||||
|
||||
@interface PXSourceListDelegateDataSourceProxy : NSProxy <NSOutlineViewDelegate, NSOutlineViewDataSource, PXSourceListDelegate, PXSourceListDataSource>
|
||||
|
||||
@property (weak, nonatomic) PXSourceList *sourceList;
|
||||
@property (weak, nonatomic) id <PXSourceListDelegate> delegate;
|
||||
@property (weak, nonatomic) id <PXSourceListDataSource> dataSource;
|
||||
|
||||
- (id)initWithSourceList:(PXSourceList *)sourceList;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,455 @@
|
||||
//
|
||||
// PXSourceListDelegateDataSourceProxy.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 25/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "PXSourceListDelegateDataSourceProxy.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import "PXSourceListPrivateConstants.h"
|
||||
#import "PXSourceListRuntimeAdditions.h"
|
||||
|
||||
// Internal constants.
|
||||
static NSString * const forwardingMapForwardingMethodNameKey = @"methodName";
|
||||
static NSString * const forwardingMapForwardedArgumentIndexesKey = @"forwardedArgumentIndexes";
|
||||
|
||||
static NSArray * __outlineViewDelegateMethods = nil;
|
||||
static NSArray * __outlineViewDataSourceMethods = nil;
|
||||
static NSArray * __requiredOutlineViewDataSourceMethods = nil;
|
||||
|
||||
// Cache the PXSourceListDelegate and PXSourceListDataSource method names so that if these methods are invoked on
|
||||
// us, we can quickly forward them to the delegate and dataSource using -forwardingTargetForSelector: without going
|
||||
// through -forwardInvocation:.
|
||||
static NSArray * __fastPathForwardingDelegateMethods = nil;
|
||||
static NSArray * __fastPathForwardingDataSourceMethods = nil;
|
||||
|
||||
// We want to suppress the warnings for protocol methods not being implemented. As a proxy we will forward these
|
||||
// messages to the actual delegate and data source.
|
||||
#pragma clang diagnostic ignored "-Wprotocol"
|
||||
@implementation PXSourceListDelegateDataSourceProxy
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
__outlineViewDelegateMethods = px_methodNamesForProtocol(@protocol(NSOutlineViewDelegate));
|
||||
__outlineViewDataSourceMethods = px_methodNamesForProtocol(@protocol(NSOutlineViewDataSource));
|
||||
__fastPathForwardingDelegateMethods = px_methodNamesForProtocol(@protocol(PXSourceListDelegate));
|
||||
__fastPathForwardingDataSourceMethods = px_methodNamesForProtocol(@protocol(PXSourceListDataSource));
|
||||
|
||||
__requiredOutlineViewDataSourceMethods = @[NSStringFromSelector(@selector(outlineView:numberOfChildrenOfItem:)),
|
||||
NSStringFromSelector(@selector(outlineView:child:ofItem:)),
|
||||
NSStringFromSelector(@selector(outlineView:isItemExpandable:)),
|
||||
NSStringFromSelector(@selector(outlineView:objectValueForTableColumn:byItem:))];
|
||||
|
||||
// Add the custom mappings first before we add the 'regular' mappings.
|
||||
[self addCustomMethodNameMappings];
|
||||
|
||||
// Now add the 'regular' mappings.
|
||||
[self addEntriesToMethodForwardingMap:[self methodNameMappingsForProtocol:@protocol(NSOutlineViewDelegate)]];
|
||||
[self addEntriesToMethodForwardingMap:[self methodNameMappingsForProtocol:@protocol(NSOutlineViewDataSource)]];
|
||||
}
|
||||
|
||||
- (id)initWithSourceList:(PXSourceList *)sourceList
|
||||
{
|
||||
_sourceList = sourceList;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
//Unregister the delegate from receiving notifications
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self.delegate name:nil object:self.sourceList];
|
||||
}
|
||||
|
||||
#pragma mark - Accessors
|
||||
|
||||
- (void)setDelegate:(id<PXSourceListDelegate>)delegate
|
||||
{
|
||||
if (self.delegate)
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self.delegate name:nil object:self];
|
||||
|
||||
_delegate = delegate;
|
||||
|
||||
//Register the new delegate to receive notifications
|
||||
[self registerDelegateToReceiveNotification:PXSLSelectionIsChangingNotification
|
||||
withSelector:@selector(sourceListSelectionIsChanging:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLSelectionDidChangeNotification
|
||||
withSelector:@selector(sourceListSelectionDidChange:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLItemWillExpandNotification
|
||||
withSelector:@selector(sourceListItemWillExpand:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLItemDidExpandNotification
|
||||
withSelector:@selector(sourceListItemDidExpand:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLItemWillCollapseNotification
|
||||
withSelector:@selector(sourceListItemWillCollapse:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLItemDidCollapseNotification
|
||||
withSelector:@selector(sourceListItemDidCollapse:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLDeleteKeyPressedOnRowsNotification
|
||||
withSelector:@selector(sourceListDeleteKeyPressedOnRows:)];
|
||||
}
|
||||
|
||||
- (void)setDataSource:(id<PXSourceListDataSource>)dataSource
|
||||
{
|
||||
_dataSource = dataSource;
|
||||
}
|
||||
|
||||
#pragma mark - NSObject Overrides
|
||||
|
||||
- (BOOL)respondsToSelector:(SEL)aSelector
|
||||
{
|
||||
if ([self.sourceList respondsToSelector:aSelector])
|
||||
return YES;
|
||||
|
||||
NSString *methodName = NSStringFromSelector(aSelector);
|
||||
|
||||
if ([__requiredOutlineViewDataSourceMethods containsObject:methodName])
|
||||
return YES;
|
||||
|
||||
if ([__fastPathForwardingDelegateMethods containsObject:methodName])
|
||||
return [self.delegate respondsToSelector:aSelector];
|
||||
if ([__fastPathForwardingDataSourceMethods containsObject:methodName])
|
||||
return [self.dataSource respondsToSelector:aSelector];
|
||||
|
||||
id forwardingObject = [self forwardingObjectForSelector:aSelector];
|
||||
NSDictionary *forwardingInformation = [[self class] forwardingInformationForSelector:aSelector];
|
||||
|
||||
if(!forwardingObject || !forwardingInformation)
|
||||
return NO;
|
||||
|
||||
return [forwardingObject respondsToSelector:NSSelectorFromString(forwardingInformation[forwardingMapForwardingMethodNameKey])];
|
||||
}
|
||||
|
||||
- (BOOL)conformsToProtocol:(Protocol *)protocol
|
||||
{
|
||||
return class_conformsToProtocol(object_getClass(self), protocol);
|
||||
}
|
||||
|
||||
- (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])
|
||||
description = px_methodDescriptionForProtocolMethod(@protocol(NSOutlineViewDelegate), aSelector);
|
||||
else if ([__outlineViewDataSourceMethods containsObject:methodName])
|
||||
description = px_methodDescriptionForProtocolMethod(@protocol(NSOutlineViewDataSource), aSelector);
|
||||
|
||||
if (description.name == NULL && description.types == NULL)
|
||||
return nil;
|
||||
|
||||
return [NSMethodSignature signatureWithObjCTypes:description.types];
|
||||
}
|
||||
|
||||
- (void)forwardInvocation:(NSInvocation *)anInvocation
|
||||
{
|
||||
SEL sourceSelector = anInvocation.selector;
|
||||
|
||||
// Give the Source List a chance to handle the selector first (this is a bit of a hack for the time being
|
||||
// and should be changed).
|
||||
if ([self.sourceList respondsToSelector:sourceSelector]) {
|
||||
[anInvocation invokeWithTarget:self.sourceList];
|
||||
return;
|
||||
}
|
||||
|
||||
id forwardingObject = [self forwardingObjectForSelector:sourceSelector];
|
||||
NSDictionary *forwardingInformation = [[self class] forwardingInformationForSelector:sourceSelector];
|
||||
|
||||
if(!forwardingObject || !forwardingInformation) {
|
||||
[super forwardInvocation:anInvocation];
|
||||
return;
|
||||
}
|
||||
|
||||
SEL forwardingSelector = NSSelectorFromString(forwardingInformation[forwardingMapForwardingMethodNameKey]);
|
||||
|
||||
NSArray *forwardedArgumentIndexes = forwardingInformation[forwardingMapForwardedArgumentIndexesKey];
|
||||
anInvocation.selector = forwardingSelector;
|
||||
|
||||
NSMethodSignature *methodSignature = [forwardingObject methodSignatureForSelector:forwardingSelector];
|
||||
|
||||
/* Catch the case where we have advertised ourselves as responding to a selector required by NSOutlineView
|
||||
for a valid dataSource but the corresponding PXSourceListDataSource method isn't implemented by the dataSource.
|
||||
*/
|
||||
if ([__requiredOutlineViewDataSourceMethods containsObject:NSStringFromSelector(sourceSelector)]
|
||||
&& ![self.dataSource respondsToSelector:forwardingSelector]) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Modify the arguments in the invocation if the source and target selector arguments are different.
|
||||
|
||||
The forwardedArgumentIndexes array contains the indexes of arguments in the original invocation that we want
|
||||
to use in our modified invocation. E.g. @[@0, @2] means take the first and third arguments and only use them
|
||||
when forwarding. We want to do this when the forwarded selector has a different number of arguments to the
|
||||
source selector (see +addCustomMethodNameMappings).
|
||||
|
||||
Note that this implementation only works if the arguments in `forwardedArgumentIndexes` are monotonically
|
||||
increasing (which is good enough for now).
|
||||
|
||||
*/
|
||||
if (forwardedArgumentIndexes) {
|
||||
// self and _cmd are arguments 0 and 1.
|
||||
NSUInteger invocationArgumentIndex = 2;
|
||||
for (NSNumber *newArgumentIndex in forwardedArgumentIndexes) {
|
||||
NSInteger forwardedArgumentIndex = newArgumentIndex.integerValue;
|
||||
|
||||
// Handle the case where we want to use (for example) the third argument from the original invocation
|
||||
// as the second argument of our modified invocation.
|
||||
if (invocationArgumentIndex != forwardedArgumentIndex) {
|
||||
NSUInteger argumentSize = 0;
|
||||
NSGetSizeAndAlignment([methodSignature getArgumentTypeAtIndex:invocationArgumentIndex], &argumentSize, NULL);
|
||||
|
||||
void *argument = malloc(argumentSize);
|
||||
[anInvocation getArgument:argument atIndex:forwardedArgumentIndex + 2]; // Take self and _cmd into account again.
|
||||
[anInvocation setArgument:argument atIndex:invocationArgumentIndex];
|
||||
free(argument);
|
||||
}
|
||||
|
||||
invocationArgumentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
[anInvocation invokeWithTarget:forwardingObject];
|
||||
}
|
||||
|
||||
- (id)forwardingTargetForSelector:(SEL)aSelector
|
||||
{
|
||||
NSString *methodName = NSStringFromSelector(aSelector);
|
||||
|
||||
if ([__fastPathForwardingDelegateMethods containsObject:methodName])
|
||||
return self.delegate;
|
||||
|
||||
if ([__fastPathForwardingDataSourceMethods containsObject:methodName])
|
||||
return self.dataSource;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - Method Forwarding
|
||||
|
||||
+ (NSMutableDictionary *)methodForwardingMap
|
||||
{
|
||||
static NSMutableDictionary *_methodForwardingMap = nil;
|
||||
if (!_methodForwardingMap)
|
||||
_methodForwardingMap = [[NSMutableDictionary alloc] init];
|
||||
|
||||
return _methodForwardingMap;
|
||||
}
|
||||
|
||||
+ (void)addEntriesToMethodForwardingMap:(NSDictionary *)entries
|
||||
{
|
||||
NSArray *methodForwardingBlacklist = [self methodForwardingBlacklist];
|
||||
NSMutableDictionary *methodForwardingMap = [self methodForwardingMap];
|
||||
|
||||
for (NSString *key in entries) {
|
||||
if (![methodForwardingBlacklist containsObject:key] && !methodForwardingMap[key])
|
||||
methodForwardingMap[key] = entries[key];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary *)methodNameMappingsForProtocol:(Protocol *)protocol
|
||||
{
|
||||
NSMutableDictionary *methodNameMappings = [[NSMutableDictionary alloc] init];
|
||||
NSArray *protocolMethods = px_allProtocolMethods(protocol);
|
||||
NSString *protocolName = NSStringFromProtocol(protocol);
|
||||
|
||||
for (NSDictionary *methodInfo in protocolMethods) {
|
||||
NSString *methodName = methodInfo[px_protocolMethodNameKey];
|
||||
NSString *mappedMethodName = [self mappedMethodNameForMethodName:methodName];
|
||||
if (!mappedMethodName) {
|
||||
NSLog(@"PXSourceList: couldn't map method %@ from %@", methodName, protocolName);
|
||||
continue;
|
||||
}
|
||||
|
||||
[methodNameMappings setObject:@{forwardingMapForwardingMethodNameKey: mappedMethodName}
|
||||
forKey:methodName];
|
||||
}
|
||||
|
||||
return methodNameMappings;
|
||||
}
|
||||
|
||||
+ (NSString *)mappedMethodNameForMethodName:(NSString *)methodName
|
||||
{
|
||||
NSString *outlineViewSearchString = @"outlineView";
|
||||
NSUInteger letterVOffset = [outlineViewSearchString rangeOfString:@"V"].location;
|
||||
NSCharacterSet *uppercaseLetterCharacterSet = [NSCharacterSet uppercaseLetterCharacterSet];
|
||||
|
||||
NSRange outlineViewStringRange = [methodName rangeOfString:outlineViewSearchString options:NSCaseInsensitiveSearch];
|
||||
|
||||
// If for some reason we can't map the method name, try to fail gracefully.
|
||||
if (outlineViewStringRange.location == NSNotFound)
|
||||
return nil;
|
||||
|
||||
BOOL isOCapitalized = [uppercaseLetterCharacterSet characterIsMember:[methodName characterAtIndex:outlineViewStringRange.location]];
|
||||
BOOL isVCapitalized = [uppercaseLetterCharacterSet characterIsMember:[methodName characterAtIndex:outlineViewStringRange.location + letterVOffset]];
|
||||
return [methodName stringByReplacingCharactersInRange:outlineViewStringRange
|
||||
withString:[NSString stringWithFormat:@"%@ource%@ist", isOCapitalized ? @"S" : @"s", isVCapitalized ? @"L" : @"l"]];
|
||||
|
||||
}
|
||||
|
||||
- (id)forwardingObjectForSelector:(SEL)selector
|
||||
{
|
||||
if ([__outlineViewDataSourceMethods containsObject:NSStringFromSelector(selector)])
|
||||
return self.dataSource;
|
||||
|
||||
if ([__outlineViewDelegateMethods containsObject:NSStringFromSelector(selector)])
|
||||
return self.delegate;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)forwardingInformationForSelector:(SEL)selector
|
||||
{
|
||||
return [[self methodForwardingMap] objectForKey:NSStringFromSelector(selector)];
|
||||
}
|
||||
|
||||
// These methods won't have mappings created for them.
|
||||
+ (NSArray *)methodForwardingBlacklist
|
||||
{
|
||||
return @[NSStringFromSelector(@selector(outlineView:shouldSelectTableColumn:)),
|
||||
NSStringFromSelector(@selector(outlineView:shouldReorderColumn:toColumn:)),
|
||||
NSStringFromSelector(@selector(outlineView:mouseDownInHeaderOfTableColumn:)),
|
||||
NSStringFromSelector(@selector(outlineView:didClickTableColumn:)),
|
||||
NSStringFromSelector(@selector(outlineView:didDragTableColumn:)),
|
||||
NSStringFromSelector(@selector(outlineView:sizeToFitWidthOfColumn:)),
|
||||
NSStringFromSelector(@selector(outlineView:shouldReorderColumn:toColumn:)),
|
||||
NSStringFromSelector(@selector(outlineViewColumnDidMove:)),
|
||||
NSStringFromSelector(@selector(outlineViewColumnDidResize:)),
|
||||
NSStringFromSelector(@selector(outlineView:isGroupItem:))];
|
||||
}
|
||||
|
||||
/* Add custom mappings for method names which can't have "outlineView" simply replaced with "sourceList".
|
||||
|
||||
For example, -outlineView:objectValueForTableColumn:byItem: should be forwarded to -sourceList:objectValueForItem:. We also only want to
|
||||
forward the 1st and 3rd arguments when invoking this second selector.
|
||||
|
||||
*/
|
||||
+ (void)addCustomMethodNameMappings
|
||||
{
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:objectValueForTableColumn:byItem:)
|
||||
toSelector:@selector(sourceList:objectValueForItem:)
|
||||
forwardedArgumentIndexes:@[@0, @2]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:setObjectValue:forTableColumn:byItem:)
|
||||
toSelector:@selector(sourceList:setObjectValue:forItem:)
|
||||
forwardedArgumentIndexes:@[@0, @1, @3]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:viewForTableColumn:item:)
|
||||
toSelector:@selector(sourceList:viewForItem:)
|
||||
forwardedArgumentIndexes:@[@0, @2]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:willDisplayCell:forTableColumn:item:)
|
||||
toSelector:@selector(sourceList:willDisplayCell:forItem:)
|
||||
forwardedArgumentIndexes:@[@0, @1, @3]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:shouldEditTableColumn:item:)
|
||||
toSelector:@selector(sourceList:shouldEditItem:)
|
||||
forwardedArgumentIndexes:@[@0, @2]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:)
|
||||
toSelector:@selector(sourceList:toolTipForCell:rect:item:mouseLocation:)
|
||||
forwardedArgumentIndexes:@[@0, @1, @2, @4, @5]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:typeSelectStringForTableColumn:item:)
|
||||
toSelector:@selector(sourceList:typeSelectStringForItem:)
|
||||
forwardedArgumentIndexes:@[@0, @2]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:shouldShowCellExpansionForTableColumn:item:)
|
||||
toSelector:@selector(sourceList:shouldShowCellExpansionForItem:)
|
||||
forwardedArgumentIndexes:@[@0, @2]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:shouldTrackCell:forTableColumn:item:)
|
||||
toSelector:@selector(sourceList:shouldTrackCell:forItem:)
|
||||
forwardedArgumentIndexes:@[@0, @1, @3]];
|
||||
[self addCustomMethodNameMappingFromSelector:@selector(outlineView:dataCellForTableColumn:item:)
|
||||
toSelector:@selector(sourceList:dataCellForItem:)
|
||||
forwardedArgumentIndexes:@[@0, @2]];
|
||||
}
|
||||
|
||||
+ (void)addCustomMethodNameMappingFromSelector:(SEL)fromSelector toSelector:(SEL)toSelector forwardedArgumentIndexes:(NSArray *)argumentIndexes
|
||||
{
|
||||
[[self methodForwardingMap] setObject:@{forwardingMapForwardingMethodNameKey: NSStringFromSelector(toSelector),
|
||||
forwardingMapForwardedArgumentIndexesKey: argumentIndexes}
|
||||
forKey:NSStringFromSelector(fromSelector)];
|
||||
}
|
||||
|
||||
- (BOOL)getForwardingObject:(id*)outObject andForwardingSelector:(SEL*)outSelector forSelector:(SEL)selector
|
||||
{
|
||||
NSDictionary *methodForwardingMap = [[self class] methodForwardingMap];
|
||||
NSString *originalMethodName = NSStringFromSelector(selector);
|
||||
NSDictionary *forwardingInfo = methodForwardingMap[originalMethodName];
|
||||
if (!forwardingInfo)
|
||||
return NO;
|
||||
|
||||
id forwardingObject;
|
||||
if ([__outlineViewDelegateMethods containsObject:originalMethodName])
|
||||
forwardingObject = self.delegate;
|
||||
else if ([__outlineViewDataSourceMethods containsObject:originalMethodName])
|
||||
forwardingObject = self.dataSource;
|
||||
|
||||
if (!forwardingObject)
|
||||
return NO;
|
||||
|
||||
if (outObject)
|
||||
*outObject = forwardingObject;
|
||||
|
||||
if (outSelector)
|
||||
*outSelector = NSSelectorFromString(forwardingInfo[forwardingMapForwardingMethodNameKey]);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Notifications
|
||||
|
||||
- (void)registerDelegateToReceiveNotification:(NSString*)notification withSelector:(SEL)selector
|
||||
{
|
||||
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
|
||||
|
||||
//Set the delegate as a receiver of the notification if it implements the notification method
|
||||
if([self.delegate respondsToSelector:selector]) {
|
||||
[defaultCenter addObserver:self.delegate
|
||||
selector:selector
|
||||
name:notification
|
||||
object:self.sourceList];
|
||||
}
|
||||
}
|
||||
|
||||
/* Notification wrappers */
|
||||
- (void)outlineViewSelectionIsChanging:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLSelectionIsChangingNotification object:self.sourceList];
|
||||
}
|
||||
|
||||
|
||||
- (void)outlineViewSelectionDidChange:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLSelectionDidChangeNotification object:self.sourceList];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemWillExpand:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLItemWillExpandNotification
|
||||
object:self.sourceList
|
||||
userInfo:[notification userInfo]];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemDidExpand:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLItemDidExpandNotification
|
||||
object:self.sourceList
|
||||
userInfo:[notification userInfo]];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemWillCollapse:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLItemWillCollapseNotification
|
||||
object:self.sourceList
|
||||
userInfo:[notification userInfo]];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemDidCollapse:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLItemDidCollapseNotification
|
||||
object:self.sourceList
|
||||
userInfo:[notification userInfo]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// PXSourceListPrivateConstants.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 25/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSString * const PXSLSelectionIsChangingNotification;
|
||||
extern NSString * const PXSLSelectionDidChangeNotification;
|
||||
extern NSString * const PXSLItemWillExpandNotification;
|
||||
extern NSString * const PXSLItemDidExpandNotification;
|
||||
extern NSString * const PXSLItemWillCollapseNotification;
|
||||
extern NSString * const PXSLItemDidCollapseNotification;
|
||||
extern NSString * const PXSLDeleteKeyPressedOnRowsNotification;
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// PXSourceListRuntimeAdditions.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 25/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
extern NSString * const px_protocolMethodNameKey;
|
||||
extern NSString * const px_protocolMethodArgumentTypesKey;
|
||||
extern NSString * const px_protocolIsRequiredMethodKey;
|
||||
|
||||
NSArray *px_allProtocolMethods(Protocol *protocol);
|
||||
NSArray *px_methodNamesForProtocol(Protocol *protocol);
|
||||
|
||||
struct objc_method_description px_methodDescriptionForProtocolMethod(Protocol *protocol, SEL selector);
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// PXSourceListRuntimeAdditions.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 25/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "PXSourceListRuntimeAdditions.h"
|
||||
|
||||
NSString * const px_protocolMethodNameKey = @"methodName";
|
||||
NSString * const px_protocolMethodArgumentTypesKey = @"types";
|
||||
NSString * const px_protocolIsRequiredMethodKey = @"isRequired";
|
||||
|
||||
NSArray *px_allProtocolMethods(Protocol *protocol)
|
||||
{
|
||||
NSMutableArray *methodList = [[NSMutableArray alloc] init];
|
||||
|
||||
// We have 4 permutations as protocol_copyMethodDescriptionList() takes two BOOL arguments for the types of methods to return.
|
||||
for (NSUInteger i = 0; i < 4; ++i) {
|
||||
BOOL isRequiredMethod = (i / 2) % 2;
|
||||
|
||||
unsigned int numberOfMethodDescriptions = 0;
|
||||
struct objc_method_description *methodDescriptions = protocol_copyMethodDescriptionList(protocol, isRequiredMethod, i % 2, &numberOfMethodDescriptions);
|
||||
|
||||
for (unsigned int j = 0; j < numberOfMethodDescriptions; ++j) {
|
||||
struct objc_method_description methodDescription = methodDescriptions[j];
|
||||
[methodList addObject:@{px_protocolMethodNameKey: NSStringFromSelector(methodDescription.name),
|
||||
px_protocolMethodArgumentTypesKey: [NSString stringWithUTF8String:methodDescription.types],
|
||||
px_protocolIsRequiredMethodKey: @(isRequiredMethod)}];
|
||||
}
|
||||
|
||||
free(methodDescriptions);
|
||||
}
|
||||
|
||||
return methodList;
|
||||
}
|
||||
|
||||
NSArray *px_methodNamesForProtocol(Protocol *protocol)
|
||||
{
|
||||
NSMutableArray *methodNames = [[NSMutableArray alloc] init];
|
||||
|
||||
for (NSDictionary *methodInfo in px_allProtocolMethods(protocol))
|
||||
[methodNames addObject:methodInfo[px_protocolMethodNameKey]];
|
||||
|
||||
return methodNames;
|
||||
}
|
||||
|
||||
struct objc_method_description px_methodDescriptionForProtocolMethod(Protocol *protocol, SEL selector)
|
||||
{
|
||||
struct objc_method_description description = {NULL, NULL};
|
||||
|
||||
// We have 4 permutations to check for.
|
||||
for (NSUInteger i = 0; i < 4; ++i) {
|
||||
description = protocol_getMethodDescription(protocol, selector, (i / 2) % 2, i % 2);
|
||||
if (description.types != NULL && description.name != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
return description;
|
||||
}
|
||||
@@ -3,38 +3,204 @@
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 05/09/2009.
|
||||
// Copyright 2009-10 Alex Rozanski http://perspx.com
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "PXSourceListDelegate.h"
|
||||
#import "PXSourceListDataSource.h"
|
||||
#import "PXSourceListItem.h"
|
||||
#import "PXSourceListBadgeView.h"
|
||||
#import "PXSourceListTableCellView.h"
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
@protocol NSOutlineViewDelegate <NSObject> @end
|
||||
@protocol NSOutlineViewDataSource <NSObject> @end
|
||||
#endif
|
||||
/**
|
||||
|
||||
`PXSourceList` is an `NSOutlineView` subclass that makes using a source list (the sidebar
|
||||
seen in applications such as iTunes and Mail.app) easier by providing common styling and idiomatic
|
||||
behaviour of source lists for you through a clean and simple API. Notable features of PXSourceList include:
|
||||
|
||||
- All root-level, "group" items are displayed using `NSOutlineView`'s group styling by default and requires no additional setup.
|
||||
- Source List items often display an *icon* and *badge* (for information such as unread counts). This is built into
|
||||
the API to make configuring these quick and easy, and a badge `NSControl` subclass is included which can be added to
|
||||
`NSTableCellView` objects when using `PXSourceList` in *view-based* mode to display badges (see the next section for details).
|
||||
- `PXSourceList` implements support for showing groups as "always expanded" -- where their child items are always shown
|
||||
and no 'Show'/'Hide' button is displayed when hovering over the group. This is often useful for listing the main
|
||||
contexts your application can be in at any given time, which the user can select to change views. As it is paramount to
|
||||
your application's navigation, these groups are often displayed with their child items always shown.
|
||||
- `PXSourceList` objects operate with only one column and do not display a header, something
|
||||
which is reflected in the API and makes the control easier to use.
|
||||
|
||||
Like `NSOutlineView` and `NSTableView`, a `PXSourceList` object does not store its own data, but retrieves
|
||||
values from a weakly-referenced data source (see the `PXSourceListDataSource` protocol). A `PXSourceList`
|
||||
object can also have a delegate, to which it sends messages when certain events occur (see the
|
||||
`PXSourceListDelegate` protocol for more information).
|
||||
|
||||
### Cell-based vs. view-based mode
|
||||
|
||||
Like `NSTableView` and `NSOutlineView`, PXSourceList can operate in both cell-based and view-based mode in
|
||||
relation to how you provide content to be displayed.
|
||||
|
||||
When using PXSourceList in cell-based mode, it can manage drawing of icons and badges for you through custom
|
||||
drawing and `PXSourceListDataSource` methods. However, when using PXSourceList in view-based mode, it can't
|
||||
do this directly, because cell views are configured independently in Interface Builder (or programmatically)
|
||||
and configured in the `PXSourceListDataSource` method, `-sourceList:viewForItem:`.
|
||||
|
||||
Instead, in view-based mode, you should set up the icon for each item in `-sourceList:viewForItem:` using the
|
||||
`imageView` property of `NSTableCellView`, and the `badgeView` property if using `PXSourceListTableCellView`
|
||||
objects to display your content. Additionally, there are several classes provided alongside `PXSourceList`
|
||||
which make this set up a lot easier:
|
||||
|
||||
- `PXSourceListTableCellView`: an `NSTableCellView` subclass which exposes a `badgeView` outlet that can be
|
||||
hooked up to a `PXSourceListBadgeView` instance (see below) in Interface Builder. Along with `NSTableCellView`
|
||||
and its `textField` and `imageView` properties, `PXSourceListTableCellView` is an `NSTableCellView` subclass which
|
||||
allows you to easily display an icon, title and a badge for each item in the Source List without subclassing.
|
||||
- `PXSourceListBadgeView`: a view class for displaying badges, which can be used in your table cell views and
|
||||
configured to display a particular badge number. Additionally, instances can be configured to use custom text and
|
||||
background colours, although it will use the regular Source List styling of light text on a grey-blue background
|
||||
by default.
|
||||
|
||||
### Creating a data source model with `PXSourceListItem`
|
||||
|
||||
Like `NSOutlineView`, PXSourceList queries its data source to build up a tree-like structure of content using
|
||||
`-sourceList:numberOfChildrenOfItem:` and `-sourceList:child:ofItem:`. Often it is practical to store the structure
|
||||
of your Source List content in a tree structure which can then be easily returned the the Source List using
|
||||
these two data source methods.
|
||||
|
||||
To help with this, the generic `PXSourceListItem` class has been included with PXSourceList which can be
|
||||
used to build this tree structure. It declares properties such as `title` and `icon` which are useful in
|
||||
storing display information which can then be used in `-sourceList:viewForItem:` or `-sourceList:objectValueForItem:`,
|
||||
as well as a `children` property with convenience methods for mutating its list of children. Take a look at the
|
||||
`PXSourceListItem` documentation for more information, as well as the cell-based and view-based example
|
||||
projects included for examples of how to use this class in your own projects.
|
||||
|
||||
*/
|
||||
@interface PXSourceList: NSOutlineView <NSOutlineViewDelegate, NSOutlineViewDataSource>
|
||||
{
|
||||
id <PXSourceListDelegate> _secondaryDelegate; //Used to store the publicly visible delegate
|
||||
id <PXSourceListDataSource> _secondaryDataSource; //Used to store the publicly visible data source
|
||||
|
||||
NSSize _iconSize; //The size of icons in the Source List. Defaults to 16x16
|
||||
}
|
||||
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Delegate and Data Source
|
||||
///---------------------------------------------------------------------------------------
|
||||
|
||||
/** Used to set the Source List's data source.
|
||||
|
||||
@warning Unfortunately, due to the way that `PXSourceList` is implemented, sending `-dataSource` to the Source List
|
||||
will return a proxy object which is used internally. As such you should only use this setter and not invoke `-dataSource`
|
||||
to retrieve the data source object.
|
||||
|
||||
@param dataSource An object to use for the data source.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)setDataSource:(id<PXSourceListDataSource>)dataSource;
|
||||
|
||||
/** Used to set the Source List's delegate.
|
||||
|
||||
@warning Unfortunately, due to the way that `PXSourceList` is implemented, sending `-delegate` to the Source List
|
||||
will return a proxy object which is used internally. As such you should only use this setter and not invoke `-delegate`
|
||||
to retrieve the data source object.
|
||||
|
||||
@param delegate An object to use for the delegate.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)setDelegate:(id<PXSourceListDelegate>)delegate;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Setting Display Attributes
|
||||
///---------------------------------------------------------------------------------------
|
||||
|
||||
/** Returns the size of icons in points to display in items in the Source List.
|
||||
|
||||
@discussion The default value is 16 x 16.
|
||||
|
||||
@warning This property only applies when using `PXSourceList` in cell-based mode. If set on a Source List
|
||||
operating in view-based mode, this value is not used.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
|
||||
@property (nonatomic, assign) NSSize iconSize;
|
||||
|
||||
@property (assign) id<PXSourceListDataSource> dataSource;
|
||||
@property (assign) id<PXSourceListDelegate> delegate;
|
||||
|
||||
- (NSUInteger)numberOfGroups; //Returns the number of groups in the Source List
|
||||
- (BOOL)isGroupItem:(id)item; //Returns whether `item` is a group
|
||||
- (BOOL)isGroupAlwaysExpanded:(id)group; //Returns whether `group` is displayed as always expanded
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Working with Groups
|
||||
///---------------------------------------------------------------------------------------
|
||||
|
||||
- (BOOL)itemHasBadge:(id)item; //Returns whether `item` has a badge
|
||||
- (NSInteger)badgeValueForItem:(id)item; //Returns the badge value for `item`
|
||||
@property (readonly) NSUInteger numberOfGroups;
|
||||
|
||||
/** Returns a Boolean value that indicates whether a given item in the Source List is a group item.
|
||||
|
||||
@param item The item to query about.
|
||||
|
||||
@return `YES` if *item* exists in the Source List and is a group item, otherwise `NO`.
|
||||
|
||||
@discussion "Group" items are defined as root items in the Source List tree hierarchy.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)isGroupItem:(id)item;
|
||||
|
||||
/** Returns a Boolean value that indicates whether a given group item in the Source List is always expanded.
|
||||
|
||||
@param group The given group item.
|
||||
|
||||
@return `YES` if *group* is a group item in the Source List which is displayed as always expanded, or `NO` otherwise.
|
||||
|
||||
@discussion "Group" items are defined as root items in the Source List tree hierarchy. A group item that is displayed
|
||||
as always expanded doesn't show a 'Show'/'Hide' button on hover as with regular group items. It is automatically expanded
|
||||
when the Source List's data is reloaded and cannot be collapsed.
|
||||
|
||||
This method calls the `-sourceList:isGroupAlwaysExpanded:` method on the Source List's delegate to determine
|
||||
whether the particular group item is displayed as always expanded or not.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)isGroupAlwaysExpanded:(id)group;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Working with Badges
|
||||
///---------------------------------------------------------------------------------------
|
||||
|
||||
/** Returns a Boolean value that indicates whether a given item in the Source List displays a badge.
|
||||
|
||||
@param item The given item.
|
||||
|
||||
@return `YES` if the Source List is operating in cell-based mode and *item* displays a badge, or `NO` otherwise.
|
||||
|
||||
@discussion This method calls the `-sourceList:itemHasBadge:` method on the Source List's delegate to determine
|
||||
whether the item displays a badge or not.
|
||||
|
||||
@warning This method only applies when using a Source List in cell-based mode. If sent to a Source List in view-based mode, this
|
||||
method returns `NO`.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)itemHasBadge:(id)item;
|
||||
|
||||
/** Returns the integer value of the badge for a given item.
|
||||
|
||||
@param item The given item.
|
||||
|
||||
@return The integer value of the badge for *item* if the Source List is operating in cell-based mode and *item* displays a badge, or `NSNotFound` otherwise.
|
||||
|
||||
@discussion This method calls the `-sourceList:badgeValueForItem:` method on the Source List's data source to determine
|
||||
the item's badge value.
|
||||
|
||||
@warning This method only applies when using a Source List in cell-based mode. If sent to a Source List in view-based mode, this
|
||||
method returns `NSNotFound`.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSInteger)badgeValueForItem:(id)item;
|
||||
|
||||
/* === Unavailable methods ===
|
||||
|
||||
As a side-effect of PXSourceList's internal implementation, these methods shouldn't be used to query the delegate or data
|
||||
source. I am *always* looking for a way to remove this limitation. Please file an issue at https://github.com/Perspx/PXSourceList if you
|
||||
have any ideas!
|
||||
*/
|
||||
- (id <NSOutlineViewDelegate>)delegate __attribute__((unavailable("-delegate shouldn't be called on PXSourceList. See the documentation for more information.")));
|
||||
- (id <NSOutlineViewDataSource>)dataSource __attribute__((unavailable("-dataSource shouldn't be called on PXSourceList. See the documentation for more information.")));
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -3,28 +3,22 @@
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 05/09/2009.
|
||||
// Copyright 2009-10 Alex Rozanski http://perspx.com
|
||||
//
|
||||
// GC-enabled code revised by Stefan Vogt http://byteproject.net
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "PXSourceList.h"
|
||||
#import "PXSourceListBadgeCell.h"
|
||||
#import "PXSourceListDelegateDataSourceProxy.h"
|
||||
#import "PXSourceListPrivateConstants.h"
|
||||
|
||||
//Layout constants
|
||||
#define MIN_BADGE_WIDTH 22.0 //The minimum badge width for each item (default 22.0)
|
||||
#define BADGE_HEIGHT 14.0 //The badge height for each item (default 14.0)
|
||||
#define BADGE_MARGIN 5.0 //The spacing between the badge and the cell for that row
|
||||
#define ROW_RIGHT_MARGIN 5.0 //The spacing between the right edge of the badge and the edge of the table column
|
||||
#define ICON_SPACING 2.0 //The spacing between the icon and it's adjacent cell
|
||||
#define DISCLOSURE_TRIANGLE_SPACE 18.0 //The indentation reserved for disclosure triangles for non-group items
|
||||
|
||||
//Drawing constants
|
||||
#define BADGE_BACKGROUND_COLOR [NSColor colorWithCalibratedRed:(152/255.0) green:(168/255.0) blue:(202/255.0) alpha:1]
|
||||
#define BADGE_HIDDEN_BACKGROUND_COLOR [NSColor colorWithDeviceWhite:(180/255.0) alpha:1]
|
||||
#define BADGE_SELECTED_TEXT_COLOR [NSColor keyboardFocusIndicatorColor]
|
||||
#define BADGE_SELECTED_UNFOCUSED_TEXT_COLOR [NSColor colorWithCalibratedRed:(153/255.0) green:(169/255.0) blue:(203/255.0) alpha:1]
|
||||
#define BADGE_SELECTED_HIDDEN_TEXT_COLOR [NSColor colorWithCalibratedWhite:(170/255.0) alpha:1]
|
||||
#define BADGE_FONT [NSFont boldSystemFontOfSize:11]
|
||||
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.
|
||||
|
||||
//Delegate notification constants
|
||||
NSString * const PXSLSelectionIsChangingNotification = @"PXSourceListSelectionIsChanging";
|
||||
@@ -38,20 +32,15 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
#pragma mark -
|
||||
@interface PXSourceList ()
|
||||
|
||||
- (void)PXSL_setup;
|
||||
|
||||
- (NSSize)sizeOfBadgeAtRow:(NSInteger)rowIndex;
|
||||
- (void)drawBadgeForRow:(NSInteger)rowIndex inRect:(NSRect)badgeFrame;
|
||||
- (void)registerDelegateToReceiveNotification:(NSString*)notification withSelector:(SEL)selector;
|
||||
@property (strong, nonatomic) PXSourceListDelegateDataSourceProxy *delegateDataSourceProxy;
|
||||
@property (strong, readonly) PXSourceListBadgeCell *reusableBadgeCell;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@implementation PXSourceList
|
||||
|
||||
@synthesize iconSize = _iconSize;
|
||||
@dynamic dataSource;
|
||||
@dynamic delegate;
|
||||
@synthesize reusableBadgeCell = _reusableBadgeCell;
|
||||
|
||||
#pragma mark - Setup/Teardown
|
||||
|
||||
@@ -75,13 +64,8 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (void)PXSL_setup
|
||||
{
|
||||
[self setDelegate:(id<PXSourceListDelegate>)[super delegate]];
|
||||
[super setDelegate:self];
|
||||
|
||||
[self setDataSource:(id<PXSourceListDataSource>)[super dataSource]];
|
||||
[super setDataSource:self];
|
||||
|
||||
_iconSize = NSMakeSize(16,16);
|
||||
_delegateDataSourceProxy = [[PXSourceListDelegateDataSourceProxy alloc] initWithSourceList:self];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
@@ -89,57 +73,30 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
//Remove ourselves as the delegate and data source to be safe
|
||||
[super setDataSource:nil];
|
||||
[super setDelegate:nil];
|
||||
|
||||
//Unregister the delegate from receiving notifications
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:_secondaryDelegate name:nil object:self];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)finalize
|
||||
{
|
||||
//Remove ourselves as the delegate and data source to be safe
|
||||
[super setDataSource:nil];
|
||||
[super setDelegate:nil];
|
||||
|
||||
//Unregister the delegate from receiving notifications
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:_secondaryDelegate name:nil object:self];
|
||||
|
||||
[super finalize];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Custom Accessors
|
||||
|
||||
- (void)setDelegate:(id<PXSourceListDelegate>)aDelegate
|
||||
{
|
||||
//Unregister the old delegate from receiving notifications
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:_secondaryDelegate name:nil object:self];
|
||||
|
||||
_secondaryDelegate = aDelegate;
|
||||
|
||||
//Register the new delegate to receive notifications
|
||||
[self registerDelegateToReceiveNotification:PXSLSelectionIsChangingNotification
|
||||
withSelector:@selector(sourceListSelectionIsChanging:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLSelectionDidChangeNotification
|
||||
withSelector:@selector(sourceListSelectionDidChange:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLItemWillExpandNotification
|
||||
withSelector:@selector(sourceListItemWillExpand:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLItemDidExpandNotification
|
||||
withSelector:@selector(sourceListItemDidExpand:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLItemWillCollapseNotification
|
||||
withSelector:@selector(sourceListItemWillCollapse:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLItemDidCollapseNotification
|
||||
withSelector:@selector(sourceListItemDidCollapse:)];
|
||||
[self registerDelegateToReceiveNotification:PXSLDeleteKeyPressedOnRowsNotification
|
||||
withSelector:@selector(sourceListDeleteKeyPressedOnRows:)];
|
||||
self.delegateDataSourceProxy.delegate = aDelegate;
|
||||
|
||||
[super setDelegate:nil];
|
||||
if (aDelegate)
|
||||
[super setDelegate:self.delegateDataSourceProxy];
|
||||
}
|
||||
|
||||
|
||||
- (void)setDataSource:(id<PXSourceListDataSource>)aDataSource
|
||||
{
|
||||
_secondaryDataSource = aDataSource;
|
||||
|
||||
self.delegateDataSourceProxy.dataSource = aDataSource;
|
||||
|
||||
[super setDataSource:nil];
|
||||
if (aDataSource)
|
||||
[super setDataSource:self.delegateDataSourceProxy];
|
||||
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
@@ -157,20 +114,43 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
}
|
||||
}
|
||||
|
||||
- (PXSourceListBadgeCell *)reusableBadgeCell
|
||||
{
|
||||
if (!_reusableBadgeCell)
|
||||
_reusableBadgeCell = [[PXSourceListBadgeCell alloc] init];
|
||||
|
||||
return _reusableBadgeCell;
|
||||
}
|
||||
|
||||
- (BOOL)floatsGroupRows
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setFloatsGroupRows:(BOOL)value
|
||||
{
|
||||
[super setFloatsGroupRows:NO];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Data Management
|
||||
|
||||
- (BOOL)isViewBasedSourceList
|
||||
{
|
||||
return [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:viewForItem:)];
|
||||
}
|
||||
|
||||
- (void)reloadData
|
||||
{
|
||||
[super reloadData];
|
||||
|
||||
//Expand items that are displayed as always expanded
|
||||
if([_secondaryDataSource conformsToProtocol:@protocol(PXSourceListDataSource)] &&
|
||||
[_secondaryDelegate respondsToSelector:@selector(sourceList:isGroupAlwaysExpanded:)])
|
||||
if([self.delegateDataSourceProxy conformsToProtocol:@protocol(PXSourceListDataSource)] &&
|
||||
[self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:isGroupAlwaysExpanded:)])
|
||||
{
|
||||
for(NSUInteger i=0;i<[self numberOfGroups];i++)
|
||||
{
|
||||
id item = [_secondaryDataSource sourceList:self child:i ofItem:nil];
|
||||
id item = [self.delegateDataSourceProxy sourceList:self child:i ofItem:nil];
|
||||
|
||||
if([self isGroupAlwaysExpanded:item]) {
|
||||
[self expandItem:item expandChildren:NO];
|
||||
@@ -220,8 +200,8 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (NSUInteger)numberOfGroups
|
||||
{
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:numberOfChildrenOfItem:)]) {
|
||||
return [_secondaryDataSource sourceList:self numberOfChildrenOfItem:nil];
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:numberOfChildrenOfItem:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self numberOfChildrenOfItem:nil];
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -240,8 +220,8 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
//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([_secondaryDelegate respondsToSelector:@selector(sourceList:isGroupAlwaysExpanded:)]) {
|
||||
return [_secondaryDelegate sourceList:self isGroupAlwaysExpanded:group];
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:isGroupAlwaysExpanded:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self isGroupAlwaysExpanded:group];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,22 +231,25 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (BOOL)itemHasBadge:(id)item
|
||||
{
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:itemHasBadge:)]) {
|
||||
return [_secondaryDataSource sourceList:self itemHasBadge:item];
|
||||
// Since badges are managed by custom views and logic in view-based mode, we can't determine this.
|
||||
if (self.isViewBasedSourceList)
|
||||
return NO;
|
||||
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasBadge:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self itemHasBadge:item];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSInteger)badgeValueForItem:(id)item
|
||||
{
|
||||
//Make sure that the item has a badge
|
||||
if(![self itemHasBadge:item]) {
|
||||
return NSNotFound;
|
||||
}
|
||||
{
|
||||
// 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([_secondaryDataSource respondsToSelector:@selector(sourceList:badgeValueForItem:)]) {
|
||||
return [_secondaryDataSource sourceList:self badgeValueForItem:item];
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:badgeValueForItem:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self badgeValueForItem:item];
|
||||
}
|
||||
|
||||
return NSNotFound;
|
||||
@@ -330,6 +313,9 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (NSRect)frameOfCellAtColumn:(NSInteger)column row:(NSInteger)row
|
||||
{
|
||||
if (self.isViewBasedSourceList)
|
||||
return [super frameOfCellAtColumn:column row:row];
|
||||
|
||||
id item = [self itemAtRow:row];
|
||||
|
||||
NSCell *cell = [self preparedCellAtColumn:column row:row];
|
||||
@@ -357,16 +343,16 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
}
|
||||
else
|
||||
{
|
||||
CGFloat leftIndent = [self levelForRow:row]*[self indentationPerLevel]+DISCLOSURE_TRIANGLE_SPACE;
|
||||
CGFloat leftIndent = [self levelForRow:row]*[self indentationPerLevel]+disclosureTriangleSpace;
|
||||
|
||||
//Calculate space left for a badge if need be
|
||||
CGFloat rightIndent = [self sizeOfBadgeAtRow:row].width+ROW_RIGHT_MARGIN;
|
||||
CGFloat rightIndent = [self sizeOfBadgeAtRow:row].width+rowRightMargin;
|
||||
|
||||
//Allow space for an icon if need be
|
||||
if(![self isGroupItem:item]&&[_secondaryDataSource respondsToSelector:@selector(sourceList:itemHasIcon:)])
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasIcon:)])
|
||||
{
|
||||
if([_secondaryDataSource sourceList:self itemHasIcon:item]) {
|
||||
leftIndent += [self iconSize].width+(ICON_SPACING*2);
|
||||
if([self.delegateDataSourceProxy sourceList:self itemHasIcon:item]) {
|
||||
leftIndent += [self iconSize].width+(iconSpacing*2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,27 +369,13 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
- (NSSize)sizeOfBadgeAtRow:(NSInteger)rowIndex
|
||||
{
|
||||
id rowItem = [self itemAtRow:rowIndex];
|
||||
|
||||
//Make sure that the item has a badge
|
||||
if(![self itemHasBadge:rowItem]) {
|
||||
|
||||
if (![self itemHasBadge:rowItem])
|
||||
return NSZeroSize;
|
||||
}
|
||||
|
||||
NSAttributedString *badgeAttrString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld", (long)[self badgeValueForItem:rowItem]]
|
||||
attributes:[NSDictionary dictionaryWithObjectsAndKeys:BADGE_FONT, NSFontAttributeName, nil]];
|
||||
|
||||
NSSize stringSize = [badgeAttrString size];
|
||||
|
||||
//Calculate the width needed to display the text or the minimum width if it's smaller
|
||||
CGFloat width = stringSize.width+(2*BADGE_MARGIN);
|
||||
|
||||
if(width<MIN_BADGE_WIDTH) {
|
||||
width = MIN_BADGE_WIDTH;
|
||||
}
|
||||
|
||||
[badgeAttrString release];
|
||||
|
||||
return NSMakeSize(width, BADGE_HEIGHT);
|
||||
|
||||
self.reusableBadgeCell.integerValue = [self badgeValueForItem:rowItem];
|
||||
|
||||
return NSMakeSize(fmax(self.reusableBadgeCell.cellSize.width, minBadgeWidth), badgeHeight);
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToSuperview
|
||||
@@ -418,24 +390,28 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
- (void)drawRow:(NSInteger)rowIndex clipRect:(NSRect)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]&&[_secondaryDataSource respondsToSelector:@selector(sourceList:itemHasIcon:)])
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasIcon:)])
|
||||
{
|
||||
if([_secondaryDataSource sourceList:self itemHasIcon:item])
|
||||
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-ICON_SPACING,
|
||||
NSRect iconRect = NSMakeRect(NSMinX(cellFrame)-iconSize.width-iconSpacing,
|
||||
NSMidY(cellFrame)-(iconSize.height/2.0f),
|
||||
iconSize.width,
|
||||
iconSize.height);
|
||||
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:iconForItem:)])
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:iconForItem:)])
|
||||
{
|
||||
NSImage *icon = [_secondaryDataSource sourceList:self iconForItem:item];
|
||||
NSImage *icon = [self.delegateDataSourceProxy sourceList:self iconForItem:item];
|
||||
|
||||
if(icon!=nil)
|
||||
{
|
||||
@@ -477,7 +453,7 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
NSRect rowRect = [self rectOfRow:rowIndex];
|
||||
NSSize badgeSize = [self sizeOfBadgeAtRow:rowIndex];
|
||||
|
||||
NSRect badgeFrame = NSMakeRect(NSMaxX(rowRect)-badgeSize.width-ROW_RIGHT_MARGIN,
|
||||
NSRect badgeFrame = NSMakeRect(NSMaxX(rowRect)-badgeSize.width-rowRightMargin,
|
||||
NSMidY(rowRect)-(badgeSize.height/2.0),
|
||||
badgeSize.width,
|
||||
badgeSize.height);
|
||||
@@ -488,87 +464,16 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (void)drawBadgeForRow:(NSInteger)rowIndex inRect:(NSRect)badgeFrame
|
||||
{
|
||||
id rowItem = [self itemAtRow:rowIndex];
|
||||
|
||||
NSBezierPath *badgePath = [NSBezierPath bezierPathWithRoundedRect:badgeFrame
|
||||
xRadius:(BADGE_HEIGHT/2.0)
|
||||
yRadius:(BADGE_HEIGHT/2.0)];
|
||||
|
||||
//Get window and control state to determine colours used
|
||||
BOOL isVisible = [[NSApp mainWindow] isVisible];
|
||||
BOOL isFocused = [[[self window] firstResponder] isEqual:self];
|
||||
NSInteger rowBeingEdited = [self editedRow];
|
||||
|
||||
//Set the attributes based on the row state
|
||||
NSDictionary *attributes;
|
||||
NSColor *backgroundColor;
|
||||
|
||||
if([[self selectedRowIndexes] containsIndex:rowIndex])
|
||||
{
|
||||
backgroundColor = [NSColor whiteColor];
|
||||
|
||||
//Set the text color based on window and control state
|
||||
NSColor *textColor;
|
||||
|
||||
if(isVisible && (isFocused || rowBeingEdited==rowIndex)) {
|
||||
textColor = BADGE_SELECTED_TEXT_COLOR;
|
||||
}
|
||||
else if(isVisible && !isFocused) {
|
||||
textColor = BADGE_SELECTED_UNFOCUSED_TEXT_COLOR;
|
||||
}
|
||||
else {
|
||||
textColor = BADGE_SELECTED_HIDDEN_TEXT_COLOR;
|
||||
}
|
||||
|
||||
attributes = [[NSDictionary alloc] initWithObjectsAndKeys:BADGE_FONT, NSFontAttributeName,
|
||||
textColor, NSForegroundColorAttributeName, nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
//Set the text colour based on window and control state
|
||||
NSColor *badgeColor = [NSColor whiteColor];
|
||||
|
||||
if(isVisible) {
|
||||
//If the data source returns a custom colour..
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:badgeBackgroundColorForItem:)]) {
|
||||
backgroundColor = [_secondaryDataSource sourceList:self badgeBackgroundColorForItem:rowItem];
|
||||
|
||||
if(backgroundColor==nil)
|
||||
backgroundColor = BADGE_BACKGROUND_COLOR;
|
||||
}
|
||||
else { //Otherwise use the default (purple-blue colour)
|
||||
backgroundColor = BADGE_BACKGROUND_COLOR;
|
||||
}
|
||||
|
||||
//If the delegate wants a custom badge text colour..
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:badgeTextColorForItem:)]) {
|
||||
badgeColor = [_secondaryDataSource sourceList:self badgeTextColorForItem:rowItem];
|
||||
|
||||
if(badgeColor==nil)
|
||||
badgeColor = [NSColor whiteColor];
|
||||
}
|
||||
}
|
||||
else { //Gray colour
|
||||
backgroundColor = BADGE_HIDDEN_BACKGROUND_COLOR;
|
||||
}
|
||||
|
||||
attributes = [[NSDictionary alloc] initWithObjectsAndKeys:BADGE_FONT, NSFontAttributeName,
|
||||
badgeColor, NSForegroundColorAttributeName, nil];
|
||||
}
|
||||
|
||||
[backgroundColor set];
|
||||
[badgePath fill];
|
||||
|
||||
//Draw the badge text
|
||||
NSAttributedString *badgeAttrString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld", (long)[self badgeValueForItem:rowItem]]
|
||||
attributes:attributes];
|
||||
NSSize stringSize = [badgeAttrString size];
|
||||
NSPoint badgeTextPoint = NSMakePoint(NSMidX(badgeFrame)-(stringSize.width/2.0), //Center in the badge frame
|
||||
NSMidY(badgeFrame)-(stringSize.height/2.0)); //Center in the badge frame
|
||||
[badgeAttrString drawAtPoint:badgeTextPoint];
|
||||
|
||||
[attributes release];
|
||||
[badgeAttrString release];
|
||||
id rowItem = [self itemAtRow:rowIndex];
|
||||
|
||||
self.reusableBadgeCell.badgeValue = [self badgeValueForItem:rowItem];
|
||||
if ([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:badgeTextColorForItem:)])
|
||||
self.reusableBadgeCell.textColor = [self.delegateDataSourceProxy sourceList:self badgeTextColorForItem:rowItem];
|
||||
if ([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:badgeBackgroundColorForItem:)])
|
||||
self.reusableBadgeCell.textColor = [self.delegateDataSourceProxy sourceList:self badgeBackgroundColorForItem:rowItem];
|
||||
self.reusableBadgeCell.highlighted = [self.selectedRowIndexes containsIndex:rowIndex];
|
||||
|
||||
[self.reusableBadgeCell drawWithFrame:badgeFrame inView:self];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -632,11 +537,11 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
- (NSMenu *)menuForEvent:(NSEvent *)theEvent
|
||||
{
|
||||
NSMenu * m = nil;
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:menuForEvent:item:)]) {
|
||||
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 = [_secondaryDelegate sourceList:self menuForEvent:theEvent item:clickedItem];
|
||||
m = [self.delegateDataSourceProxy sourceList:self menuForEvent:theEvent item:clickedItem];
|
||||
}
|
||||
if (m == nil) {
|
||||
m = [super menuForEvent:theEvent];
|
||||
@@ -644,255 +549,35 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
return m;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSOutlineView Data Source methods
|
||||
|
||||
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
|
||||
{
|
||||
if([_secondaryDataSource conformsToProtocol:@protocol(PXSourceListDataSource)]) {
|
||||
return [_secondaryDataSource sourceList:self numberOfChildrenOfItem:item];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
|
||||
{
|
||||
if([_secondaryDataSource conformsToProtocol:@protocol(PXSourceListDataSource)]) {
|
||||
return [_secondaryDataSource sourceList:self child:index ofItem:item];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
|
||||
{
|
||||
if([_secondaryDataSource conformsToProtocol:@protocol(PXSourceListDataSource)]) {
|
||||
return [_secondaryDataSource sourceList:self isItemExpandable:item];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
if([_secondaryDataSource conformsToProtocol:@protocol(PXSourceListDataSource)]) {
|
||||
return [_secondaryDataSource sourceList:self objectValueForItem:item];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
if([_secondaryDataSource conformsToProtocol:@protocol(PXSourceListDataSource)]) {
|
||||
[_secondaryDataSource sourceList:self setObjectValue:object forItem:item];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView itemForPersistentObject:(id)object
|
||||
{
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:itemForPersistentObject:)]) {
|
||||
return [_secondaryDataSource sourceList:self itemForPersistentObject:object];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item
|
||||
{
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:persistentObjectForItem:)]) {
|
||||
return [_secondaryDataSource sourceList:self persistentObjectForItem:item];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard
|
||||
{
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:writeItems:toPasteboard:)]) {
|
||||
return [_secondaryDataSource sourceList:self writeItems:items toPasteboard:pasteboard];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
|
||||
{
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:validateDrop:proposedItem:proposedChildIndex:)]) {
|
||||
return [_secondaryDataSource sourceList:self validateDrop:info proposedItem:item proposedChildIndex:index];
|
||||
}
|
||||
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(NSInteger)index
|
||||
{
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:acceptDrop:item:childIndex:)]) {
|
||||
return [_secondaryDataSource sourceList:self acceptDrop:info item:item childIndex:index];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
- (NSArray *)outlineView:(NSOutlineView *)outlineView namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination forDraggedItems:(NSArray *)items
|
||||
{
|
||||
if([_secondaryDataSource respondsToSelector:@selector(sourceList:namesOfPromisedFilesDroppedAtDestination:forDraggedItems:)]) {
|
||||
return [_secondaryDataSource sourceList:self namesOfPromisedFilesDroppedAtDestination:dropDestination forDraggedItems:items];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark 10.7 only methods
|
||||
|
||||
- (id <NSPasteboardWriting>)outlineView:(NSOutlineView *)outlineView pasteboardWriterForItem:(id)item
|
||||
{
|
||||
if ([_secondaryDataSource respondsToSelector:@selector(sourceList:pasteboardWriterForItem:)]) {
|
||||
return [_secondaryDataSource sourceList:self pasteboardWriterForItem:item];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
- (void)outlineView:(NSOutlineView *)outlineView draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint forItems:(NSArray *)draggedItems
|
||||
{
|
||||
if ([_secondaryDataSource respondsToSelector:@selector(sourceList:draggingSession:willBeginAtPoint:forItems:)]) {
|
||||
return [_secondaryDataSource sourceList:self draggingSession:session willBeginAtPoint:screenPoint forItems:draggedItems];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)outlineView:(NSOutlineView *)outlineView draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
|
||||
{
|
||||
if ([_secondaryDataSource respondsToSelector:@selector(sourceList:draggingSession:endedAtPoint:operation:)]) {
|
||||
return [_secondaryDataSource sourceList:self draggingSession:session endedAtPoint:screenPoint operation:operation];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)outlineView:(NSOutlineView *)outlineView updateDraggingItemsForDrag:(id <NSDraggingInfo>)draggingInfo
|
||||
{
|
||||
if ([_secondaryDataSource respondsToSelector:@selector(sourceList:updateDraggingItemsForDrag:)]) {
|
||||
return [_secondaryDataSource sourceList:self updateDraggingItemsForDrag:draggingInfo];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSOutlineView Delegate methods
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item
|
||||
{
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:shouldExpandItem:)]) {
|
||||
return [_secondaryDelegate sourceList:self shouldExpandItem:item];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
#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])
|
||||
{
|
||||
if([self isGroupAlwaysExpanded:item]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
// Make sure the item isn't displayed as always expanded
|
||||
if([self isGroupItem:item] && [self isGroupAlwaysExpanded:item])
|
||||
return NO;
|
||||
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:shouldCollapseItem:)]) {
|
||||
return [_secondaryDelegate sourceList:self shouldCollapseItem:item];
|
||||
}
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:shouldCollapseItem:)])
|
||||
return [self.delegateDataSourceProxy sourceList:self shouldCollapseItem:item];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:dataCellForItem:)]) {
|
||||
return [_secondaryDelegate sourceList:self dataCellForItem:item];
|
||||
}
|
||||
|
||||
NSInteger row = [self rowForItem:item];
|
||||
|
||||
//Return the default table column
|
||||
return [[[self tableColumns] objectAtIndex:0] dataCellForRow:row];
|
||||
}
|
||||
|
||||
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:willDisplayCell:forItem:)]) {
|
||||
[_secondaryDelegate sourceList:self willDisplayCell:cell forItem:item];
|
||||
}
|
||||
}
|
||||
|
||||
- (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]) {
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:shouldSelectItem:)]) {
|
||||
return [_secondaryDelegate sourceList:self shouldSelectItem:item];
|
||||
}
|
||||
}
|
||||
else {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
{
|
||||
// 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];
|
||||
|
||||
|
||||
- (NSIndexSet *)outlineView:(NSOutlineView *)outlineView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes
|
||||
{
|
||||
//The outline view will try to select the first row if -[allowsEmptySelection:] is set to NO – if this is a group row
|
||||
//stop it from doing so and leave it to our implementation of-[reloadData] which will select the first non-group row
|
||||
//for us.
|
||||
if([self numberOfSelectedRows]==0) {
|
||||
if([self isGroupItem:[self itemAtRow:[proposedSelectionIndexes firstIndex]]]) {
|
||||
return [NSIndexSet indexSet];
|
||||
}
|
||||
}
|
||||
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:selectionIndexesForProposedSelection:)]) {
|
||||
return [_secondaryDelegate sourceList:self selectionIndexesForProposedSelection:proposedSelectionIndexes];
|
||||
}
|
||||
|
||||
//Since we implement this method, something must be returned to the outline view
|
||||
return proposedSelectionIndexes;
|
||||
return ![self isGroupItem:item];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
//Group titles can't be edited
|
||||
if([self isGroupItem:item])
|
||||
return NO;
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:shouldEditItem:)])
|
||||
return [self.delegateDataSourceProxy sourceList:self shouldEditItem:item];
|
||||
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:shouldEditItem:)]) {
|
||||
return [_secondaryDelegate sourceList:self shouldEditItem:item];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldTrackCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:shouldTrackCell:forItem:)]) {
|
||||
return [_secondaryDelegate sourceList:self shouldTrackCell:cell forItem:item];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
|
||||
{
|
||||
if([_secondaryDelegate respondsToSelector:@selector(sourceList:heightOfRowByItem:)]) {
|
||||
return [_secondaryDelegate sourceList:self heightOfRowByItem:item];
|
||||
}
|
||||
|
||||
return [self rowHeight];
|
||||
return ![self isGroupItem:item];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
|
||||
@@ -900,60 +585,4 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
return [self isGroupItem:item];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Notification handling
|
||||
|
||||
/* Notification wrappers */
|
||||
- (void)outlineViewSelectionIsChanging:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLSelectionIsChangingNotification object:self];
|
||||
}
|
||||
|
||||
|
||||
- (void)outlineViewSelectionDidChange:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLSelectionDidChangeNotification object:self];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemWillExpand:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLItemWillExpandNotification
|
||||
object:self
|
||||
userInfo:[notification userInfo]];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemDidExpand:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLItemDidExpandNotification
|
||||
object:self
|
||||
userInfo:[notification userInfo]];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemWillCollapse:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLItemWillCollapseNotification
|
||||
object:self
|
||||
userInfo:[notification userInfo]];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemDidCollapse:(NSNotification *)notification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLItemDidCollapseNotification
|
||||
object:self
|
||||
userInfo:[notification userInfo]];
|
||||
}
|
||||
|
||||
- (void)registerDelegateToReceiveNotification:(NSString*)notification withSelector:(SEL)selector
|
||||
{
|
||||
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
|
||||
|
||||
//Set the delegate as a receiver of the notification if it implements the notification method
|
||||
if([_secondaryDelegate respondsToSelector:selector]) {
|
||||
[defaultCenter addObserver:_secondaryDelegate
|
||||
selector:selector
|
||||
name:notification
|
||||
object:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// PXSourceListBadgeCell.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 15/11/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
/* This is the cell which backs drawing done by PXSourceListBadgeView, and is used internally for
|
||||
drawing badges when PXSourceList is used in cell-based mode.
|
||||
|
||||
You shouldn't need to interact with this class directly.
|
||||
*/
|
||||
@interface PXSourceListBadgeCell : NSCell
|
||||
|
||||
@property (strong, nonatomic) NSColor *textColor;
|
||||
@property (strong, nonatomic) NSColor *backgroundColor;
|
||||
@property (assign, nonatomic) NSUInteger badgeValue;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// PXSourceListBadgeCell.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 15/11/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#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]; }
|
||||
static inline NSColor *badgeSelectedTextColor() { return [NSColor keyboardFocusIndicatorColor]; }
|
||||
static inline NSColor *badgeSelectedUnfocusedTextColor() { return [NSColor colorWithCalibratedRed:(153/255.0) green:(169/255.0) blue:(203/255.0) alpha:1]; }
|
||||
static inline NSColor *badgeSelectedHiddenTextColor() { return [NSColor colorWithCalibratedWhite:(170/255.0) alpha:1]; }
|
||||
static inline NSFont *badgeFont() { return [NSFont boldSystemFontOfSize:11]; }
|
||||
|
||||
// Sizing constants.
|
||||
static const CGFloat badgeLeftAndRightPadding = 5.0;
|
||||
|
||||
@implementation PXSourceListBadgeCell
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (!(self = [super initTextCell:@""]))
|
||||
return nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
|
||||
{
|
||||
CGFloat borderRadius = NSHeight(cellFrame)/2.0f;
|
||||
NSBezierPath *badgePath = [NSBezierPath bezierPathWithRoundedRect:cellFrame xRadius:borderRadius yRadius:borderRadius];
|
||||
|
||||
// Get the window and control state to determine the badge colours used.
|
||||
BOOL isMainWindowVisible = [[NSApp mainWindow] isVisible];
|
||||
NSDictionary *attributes;
|
||||
NSColor *backgroundColor;
|
||||
|
||||
if(self.isHighlighted || self.backgroundStyle == NSBackgroundStyleDark) {
|
||||
backgroundColor = [NSColor whiteColor];
|
||||
|
||||
NSResponder *firstResponder = controlView.window.firstResponder;
|
||||
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)
|
||||
textColor = badgeSelectedTextColor();
|
||||
else if (isMainWindowVisible && !isFocused)
|
||||
textColor = badgeSelectedUnfocusedTextColor();
|
||||
else
|
||||
textColor = badgeSelectedHiddenTextColor();
|
||||
|
||||
attributes = @{NSForegroundColorAttributeName: textColor};
|
||||
} else {
|
||||
NSColor *textColor = textColor = self.textColor ? self.textColor : [NSColor whiteColor];;
|
||||
|
||||
if(isMainWindowVisible)
|
||||
backgroundColor = self.backgroundColor ? self.backgroundColor : badgeBackgroundColor();
|
||||
else
|
||||
backgroundColor = badgeHiddenBackgroundColor();
|
||||
|
||||
attributes = @{NSForegroundColorAttributeName: textColor};
|
||||
}
|
||||
|
||||
[backgroundColor set];
|
||||
[badgePath fill];
|
||||
|
||||
//Draw the badge text
|
||||
NSMutableAttributedString *badgeString = [self.badgeString mutableCopy];
|
||||
[badgeString addAttributes:attributes range:NSMakeRange(0, badgeString.length)];
|
||||
|
||||
NSSize stringSize = badgeString.size;
|
||||
NSPoint badgeTextPoint = NSMakePoint(NSMidX(cellFrame) - (stringSize.width/2.0),
|
||||
NSMidY(cellFrame) - (stringSize.height/2.0));
|
||||
[badgeString drawAtPoint:badgeTextPoint];
|
||||
}
|
||||
|
||||
- (NSSize)cellSize
|
||||
{
|
||||
NSSize size = self.badgeString.size;
|
||||
size.width += 2 * badgeLeftAndRightPadding;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
- (NSAttributedString *)badgeString
|
||||
{
|
||||
return [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld", self.badgeValue]
|
||||
attributes:@{NSFontAttributeName: badgeFont()}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// PXSourceListBadgeView.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 15/11/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
/**
|
||||
`PXSourceListBadgeView` is an `NSControl` subclass which can be used for displaying Source List badges.
|
||||
|
||||
@discussion Instances of this class can be used by table cell views which are used to display content when
|
||||
using `PXSourceList` in view-based mode. These table cell views have to be set up to display badges in the
|
||||
`PXSourceListDataSource` method `-sourceList:viewForItem:` unlike when using `PXSourceList` in cell-based mode,
|
||||
where this is done automatically behind-the-scenes.
|
||||
|
||||
`PXSourceListTableCellView` has an outlet for a `PXSourceListBadgeView` instance which can be hooked up in Interface
|
||||
Builder or set in code.
|
||||
|
||||
### Display customisation
|
||||
|
||||
`PXSourceListBadgeView` displays badges like a 'system default' Source List such as in Mail.app with a grey-blue
|
||||
background and light text. However, the colours used for the badge value and the background colour of the badge can be
|
||||
changed by using the `textColor` and `backgroundColor` properties.
|
||||
|
||||
@warning Note that the `textColor` and `backgroundColor` properties are only respected when the row displaying the badge
|
||||
isn't highlighted. When the row is highlighted, the badge is displayed with a white background and a blue text colour.
|
||||
|
||||
*/
|
||||
@interface PXSourceListBadgeView : NSControl
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Reading and setting the badge value
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns the numeric value displayed by the receiver.
|
||||
|
||||
@since Requires the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
@property (assign, nonatomic) NSUInteger badgeValue;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Customising the badge appearance
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns the custom text colour used to display the receiver.
|
||||
@discussion The default value for this property is `nil`. Set this property to `nil` to use the default light badge text colour.
|
||||
|
||||
@see backgroundColor
|
||||
|
||||
@warning Note that this property is only respected when the row displaying the badge isn't highlighted. When the row is highlighted, the badge is displayed with a blue text colour.
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
@property (strong, nonatomic) NSColor *textColor;
|
||||
|
||||
/**
|
||||
@brief Returns the custom background colour used to display the receiver.
|
||||
@discussion The default value for this property is `nil`. Set this property to `nil` to use the default grey-blue badge background colour.
|
||||
|
||||
@see textColor
|
||||
|
||||
@warning Note that this property is only respected when the row displaying the badge isn't highlighted. When the row is highlighted, the badge is displayed with a white background colour.
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
@property (strong, nonatomic) NSColor *backgroundColor;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// PXSourceListBadgeView.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 15/11/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "PXSourceListBadgeView.h"
|
||||
#import "PXSourceListBadgeCell.h"
|
||||
|
||||
@implementation PXSourceListBadgeView
|
||||
|
||||
+ (Class)cellClass
|
||||
{
|
||||
return [PXSourceListBadgeCell class];
|
||||
}
|
||||
|
||||
#pragma mark - Custom Accessors
|
||||
|
||||
- (void)setBadgeValue:(NSUInteger)badgeValue
|
||||
{
|
||||
[self.cell setBadgeValue:badgeValue];
|
||||
}
|
||||
|
||||
- (NSUInteger)badgeValue
|
||||
{
|
||||
return [self.cell badgeValue];
|
||||
}
|
||||
|
||||
- (NSColor *)textColor
|
||||
{
|
||||
return [self.cell textColor];
|
||||
}
|
||||
|
||||
- (void)setTextColor:(NSColor *)textColor
|
||||
{
|
||||
[self.cell setTextColor:textColor];
|
||||
}
|
||||
|
||||
- (NSColor *)backgroundColor
|
||||
{
|
||||
return [self.cell backgroundColor];
|
||||
}
|
||||
|
||||
- (void)setBackgroundColor:(NSColor *)backgroundColor
|
||||
{
|
||||
[self.cell setBackgroundColor:backgroundColor];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -3,45 +3,394 @@
|
||||
// PXViewKit
|
||||
//
|
||||
// Created by Alex Rozanski on 17/10/2009.
|
||||
// Copyright 2009-10 Alex Rozanski http://perspx.com
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class PXSourceList;
|
||||
|
||||
/**
|
||||
The `PXSourceListDataSource` protocol defines methods that can be implemented by data sources of `PXSourceList` objects.
|
||||
|
||||
Despite many of these methods being optional in their implementation, several methods **must** be implemented by a data source of a `PXSourceList` object. These are:
|
||||
|
||||
- `sourceList:numberOfChildrenOfItem:`
|
||||
- `sourceList:child:ofItem:`
|
||||
- `sourceList:isItemExpandable:`
|
||||
- `sourceList:objectValueForItem:` (although this is optional if the Source List is operating in view-based mode).
|
||||
|
||||
### PXSourceList in View-based mode
|
||||
|
||||
As with `NSOutlineView`, `PXSourceList` can operate in cell-based or view-based mode. Of particular note, the
|
||||
following `PXSourceListDataSource` methods are *not* used by `PXSourceList` when operating in view-based mode.
|
||||
|
||||
- `-sourceList:itemHasBadge:`
|
||||
- `-sourceList:badgeValueForItem:`
|
||||
- `-sourceList:badgeTextColorForItem:`
|
||||
- `-sourceList:badgeBackgroundColorForItem:`
|
||||
- `-sourceList:itemHasIcon:`
|
||||
- `-sourceList:iconForItem:`
|
||||
|
||||
These properties can be configured in the `PXSourceListDelegate` protocol method, `-sourceList:viewForItem:`.
|
||||
|
||||
@warning Most of the methods defined by this protocol are analagous to those declared by `NSOutlineViewDataSource` (and are marked as such in the member's documentation), but are prefixed by "sourceList:" instead of "outlineView:". Only the most basic information about these methods is included here, and you should refer to the `NSOutlineViewDataSource` protocol documentation for more information.
|
||||
*/
|
||||
@protocol PXSourceListDataSource <NSObject>
|
||||
|
||||
@required
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Working with Items in a Source List
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns the number of child items of a given item.
|
||||
|
||||
@param sourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return The number of immediate child items of *item*. If *item* is `nil` then you should return the number of top-level items in the Source List item hierarchy.
|
||||
|
||||
@since Requires PXSourceList 0.8 and above and the OS X v10.5 SDK or above.
|
||||
|
||||
@see sourceList:child:ofItem:
|
||||
*/
|
||||
- (NSUInteger)sourceList:(PXSourceList*)sourceList numberOfChildrenOfItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns the direct child of a given item at the specified index.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param index The index of the child item of *item* to return.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return The immediate child of *item* at the specified *index*. If *item* is `nil`, then return the top-level item with index of *index*.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
|
||||
@see sourceList:numberOfChildrenOfItem:
|
||||
*/
|
||||
- (id)sourceList:(PXSourceList*)aSourceList child:(NSUInteger)index ofItem:(id)item;
|
||||
- (id)sourceList:(PXSourceList*)aSourceList objectValueForItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns a Boolean value indicating whether a given item in the Source List is expandable.
|
||||
@discussion An expandable item is one which contains child items, and can be expanded to display these. Additionally, if a group item is always displayed as expanded (denoted by `-sourceList:isGroupAlwaysExpanded:` from the `PXSourceListDelegate` protocol) then you must return `YES` from this method for the given group item.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` if *item* can be expanded, or `NO` otherwise.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList isItemExpandable:(id)item;
|
||||
|
||||
@optional
|
||||
/**
|
||||
@brief Returns the data object associated with a given item.
|
||||
@discussion When using the Source List in cell-based mode, returning the text to be displayed for cells representing Group items, the Source List will *not* transform the titles to uppercase so that they display like in iTunes or iCal, such as "LIBRARY". This is to account for edge cases such as words like "iTunes" which should be capitalized as "iTUNES" and so to do this you must pass uppercase titles yourself. It is strongly recommended that text displayed for group items is uppercased in this way, to fit the conventional style of Source List Group headers.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return The data object associated with `item`.
|
||||
|
||||
@warning This is a required method when using the Source List in cell-based mode.
|
||||
|
||||
@see sourceList:setObjectValue:forItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (id)sourceList:(PXSourceList*)aSourceList objectValueForItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Sets the associated object value of a specified item.
|
||||
@discussion This method must be implemented if the Source List is operating in cell-based mode and any items in the Source List are editable.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param object The new object value for the given item.
|
||||
@param item An item in the data source.
|
||||
|
||||
@see sourceList:objectValueForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceList:(PXSourceList*)aSourceList setObjectValue:(id)object forItem:(id)item;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Working with Badges
|
||||
///---------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@brief Returns a Boolean specifying whether a given item shows a badge or not.
|
||||
@discussion This method can be implemented by the data source to specify whether a given item displays a badge or not. A badge is a rounded rectangle containing a number (the badge value), displayed to the right of a row's cell.
|
||||
|
||||
This method must be implemented for the other badge-related data source methods – sourceList:badgeValueForItem:, sourceList:badgeTextColorForItem: and sourceList:badgeBackgroundColorForItem: – to be called.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` if *item* should display a badge, or `NO` otherwise.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, the view for each cell is responsible for managing a badge, if applicable.
|
||||
|
||||
@see sourceList:badgeValueForItem:
|
||||
@see sourceList:badgeTextColorForItem:
|
||||
@see sourceList:badgeBackgroundColorForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList itemHasBadge:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns an integer specifying the badge value for a particular item.
|
||||
@discussion This method can be implemented by the data source to specify a badge value for any particular item. If you want an item to display a badge, you must also implement sourceList:itemHasBadge: and return `YES` for that item. Returning `NO` for items in sourceList:itemHasBadge: means that this method will not be called for that item.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return The badge value for *item*.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, the view for each cell is responsible for managing a badge, if applicable.
|
||||
|
||||
@see sourceList:itemHasBadge:
|
||||
@see sourceList:badgeTextColorForItem:
|
||||
@see sourceList:badgeBackgroundColorForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSInteger)sourceList:(PXSourceList*)aSourceList badgeValueForItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns a color that is used for the badge text color of an item in the Source List.
|
||||
@discussion This method can be implemented by the data source to specify a custom badge color for a particular item.
|
||||
|
||||
This method is only called for *item* if you return `YES` for *item* in sourceList:itemHasBadge:.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return An `NSColor` object to use for the text color of *item*'s badge or `nil` to use the default badge text color.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, the view for each cell is responsible for managing a badge, if applicable.
|
||||
|
||||
@see sourceList:itemHasBadge:
|
||||
@see sourceList:badgeValueForItem:
|
||||
@see sourceList:badgeBackgroundColorForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSColor*)sourceList:(PXSourceList*)aSourceList badgeTextColorForItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns a color that is used for the badge background color of an item in the Source List.
|
||||
@discussion This method can be implemented by the data source to specify a custom badge background color for a particular item.
|
||||
|
||||
This method is only called for *item* if you return `YES` for *item* in sourceList:itemHasBadge:.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return An `NSColor` object to use for the background color of *item*'s badge or `nil` to use the default badge background color.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, the view for each cell is responsible for managing a badge, if applicable.
|
||||
|
||||
@see sourceList:itemHasBadge:
|
||||
@see sourceList:badgeValueForItem:
|
||||
@see sourceList:badgeTextColorForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSColor*)sourceList:(PXSourceList*)aSourceList badgeBackgroundColorForItem:(id)item;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Working with Icons
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns a Boolean value that indicates whether a given item shows an icon or not.
|
||||
@discussion This method can be implemented by the data source to specify whether items contain icons or not. Icons are images which are shown to the left of the row's cell, and provide a visual which accompanies the cell.
|
||||
|
||||
This method must be implemented if you want to return an icon with `sourceList:iconForItem:`.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` if *item* displays an icon, or `NO` otherwise.
|
||||
|
||||
@warning This method is only used and invoked by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, the view for each cell is responsible for managing its icon, if applicable.
|
||||
|
||||
@see sourceList:iconForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList itemHasIcon:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns the icon for a given item in the Source List.
|
||||
@discussion This method must be implemented by the data source if you return `YES` in `sourceList:itemHasIcon:` for any item in the Source List.
|
||||
|
||||
The maximum size of each icon is specified with the Source List's `iconSize` property. If the returned image is larger than the icon size property on the Source List, then it is proportionally resized down to fit this size.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return An `NSImage` that is to be used for the icon for *item*.
|
||||
|
||||
@warning This method is only used and invoked by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, the view for each cell is responsible for managing its icon, if applicable.
|
||||
|
||||
@see sourceList:itemHasIcon:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSImage*)sourceList:(PXSourceList*)aSourceList iconForItem:(id)item;
|
||||
|
||||
//The rest of these methods are basically "wrappers" for the NSOutlineViewDataSource methods
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Supporting Object Persistence
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Invoked by *aSourceList* to return the item for the archived *object*.
|
||||
@discussion This method is analagous to `-outlineView:itemForPersistentObject:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message
|
||||
@param object The archived representation of the item in the Source List's data source
|
||||
|
||||
@return The unarchived item corresponding to *object*.
|
||||
|
||||
@see sourceList:persistentObjectForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (id)sourceList:(PXSourceList*)aSourceList itemForPersistentObject:(id)object;
|
||||
|
||||
/**
|
||||
@brief Invoked by *aSourceList* to return an archived object for *item*.
|
||||
@discussion This method is analagous to `-outlineView:persistentObjectForItem:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return The unarchived item corresponding to *object*.
|
||||
|
||||
@see sourceList:persistentObjectForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (id)sourceList:(PXSourceList*)aSourceList persistentObjectForItem:(id)item;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Supporting Drag and Drop
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns a Boolean value indicating whether a drag operation is allowed.
|
||||
@discussion This method is analagous to `-outlineView:writeItems:toPasteboard:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param items An array of items that are participating in the drag.
|
||||
@param pboard The pasteboard to which to write the drag data.
|
||||
|
||||
@return `YES` if the drag should be allowed and the items were successfully written to the pasteboard, or `NO` otherwise.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard;
|
||||
|
||||
/**
|
||||
@brief Used by a Source List to determine a valid drop target.
|
||||
@discussion This method is analagous to `-outlineView:validateDrop:proposedItem:proposedChildIndex:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param sourceList The Source List that sent the message.
|
||||
@param info An object which contains more information about the dragging operation.
|
||||
@param item The proposed parent item.
|
||||
@param index The proposed child index of the parent.
|
||||
|
||||
@return An `NSDragOperation` value that indicates which dragging operation the Source List should perform.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSDragOperation)sourceList:(PXSourceList*)sourceList validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index;
|
||||
|
||||
/**
|
||||
@brief Returns a Boolean value specifying whether a drag operation was successful.
|
||||
@discussion This method is analagous to `-outlineView:acceptDrop:item:childIndex:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param info An object that contains more information about the dragging operation.
|
||||
@param item The parent of the item which the cursor was over when the mouse button was released.
|
||||
@param index The index of the child of `item` which the cursor was over when the mouse button was released.
|
||||
|
||||
@return `YES` if the drop was successful, or `NO` otherwise.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index;
|
||||
|
||||
/**
|
||||
@brief Returns an array of filenames (not file paths) for the created files that the receiver promises to create.
|
||||
@discussion This method is analagous to `-outlineView:namesOfPromisedFilesDroppedAtDestination:forDraggedItems:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param dropDestination The drop location where the files are created.
|
||||
@param items The items that are being dragged.
|
||||
|
||||
@return An array of filenames (not file paths) for the created files that the receiver promises to create.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSArray *)sourceList:(PXSourceList*)aSourceList namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination forDraggedItems:(NSArray *)items;
|
||||
|
||||
//Drag and drop methods added for 10.7
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Drag and drop methods for 10.7+
|
||||
///---------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@brief Invoked to allow the Source List to support multiple item dragging.
|
||||
@discussion This method is analagous to `-outlineView:pasteboardWriterForItem:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return Returns an instance of `NSPasteboardItem` or a custom object that implements the `NSPasteboardWriting` protocol. Returning `nil` excludes the item from being dragged.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (id <NSPasteboardWriting>)sourceList:(PXSourceList *)aSourceList pasteboardWriterForItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Implement this method know when the given dragging session is about to begin and potentially modify the dragging session.
|
||||
@discussion This method is analagous to `-outlineView:draggingSession:willBeginAtPoint:forItems:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List in which the drag is about to begin.
|
||||
@param session The dragging session that is about to begin.
|
||||
@param screenPoint The point onscreen at which the drag is to begin.
|
||||
@param draggedItems An array of items to be dragged, excluding items for which `sourceList:pasteboardWriterForItem:` returns `nil`.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (void)sourceList:(PXSourceList *)aSourceList draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint forItems:(NSArray *)draggedItems;
|
||||
|
||||
/**
|
||||
@brief Implement this method to know when the given dragging session has ended.
|
||||
@discussion This method is analagous to `-outlineView:draggingSession:endedAtPoint:operation:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List in which the drag ended.
|
||||
@param session The dragging session that ended.
|
||||
@param screenPoint The point onscreen at which the drag ended.
|
||||
@param operation A mask specifying the types of drag operations permitted by the dragging source.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (void)sourceList:(PXSourceList *)aSourceList draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation;
|
||||
|
||||
/**
|
||||
@brief Implement this method to enable the Source List to update dragging items as they are dragged over the view.
|
||||
@discussion This method is analagous to `-outlineView:updateDraggingItemsForDrag:` declared on `NSOutlineViewDataSource`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List in which the drag occurs.
|
||||
@param draggingInfo The dragging info object.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (void)sourceList:(PXSourceList *)aSourceList updateDraggingItemsForDrag:(id <NSDraggingInfo>)draggingInfo;
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,61 +3,520 @@
|
||||
// PXViewKit
|
||||
//
|
||||
// Created by Alex Rozanski on 17/10/2009.
|
||||
// Copyright 2009-10 Alex Rozanski http://perspx.com
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class PXSourceList;
|
||||
|
||||
/**
|
||||
The `PXSourceListDelegate` protocol defines methods that can be implemented by delegates of `PXSourceList` objects.
|
||||
|
||||
Note that additional documentation for the `PXSourceList` delegate notification constants is included in `PXSourceListDelegate.h`. This includes documentation for:
|
||||
|
||||
- `PXSLSelectionIsChangingNotification`
|
||||
- `PXSLSelectionDidChangeNotification`
|
||||
- `PXSLItemWillExpandNotification`
|
||||
- `PXSLItemDidExpandNotification`
|
||||
- `PXSLItemWillCollapseNotification`
|
||||
- `PXSLItemDidCollapseNotification`
|
||||
- `PXSLDeleteKeyPressedOnRowsNotification`
|
||||
|
||||
@warning Most of the methods defined by this protocol are analagous to those declared by `NSOutlineViewDelegate` (and are marked as such in the member's documentation), but are prefixed by "sourceList:" instead of "outlineView:". Only the most basic information about these methods is included here, and you should refer to the `NSOutlineViewDelegate` protocol documentation for more information. Several methods differ to those declared on `NSOutlineViewDelegate` in that they don't have an `NSTableColumn` parameter since `PXSourceList` works implicitly with only one table column.
|
||||
*/
|
||||
@protocol PXSourceListDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
//Extra methods
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Working with Groups
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns a Boolean value that indicates whether a particular group item is displayed as always expanded.
|
||||
@discussion A group that is displayed as *always expanded* displays no 'Show'/'Hide' button to the right on hover, and its direct children are always expanded.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param group A group item in the data source.
|
||||
|
||||
@return `YES` to specify that the group should be displayed as always expanded, or `NO` if not.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList isGroupAlwaysExpanded:(id)group;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Handling Mouse and Keyboard Input
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns a context menu which is to be displayed for a given mouse-down event.
|
||||
@discussion See `-menuForEvent:` declared on `NSView` for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param theEvent A mouse event.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return An instantiated `NSMenu` object to be displayed by the Source List for *event*, or `nil` if no menu is to be shown for the given event.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSMenu*)sourceList:(PXSourceList*)aSourceList menuForEvent:(NSEvent*)theEvent item:(id)item;
|
||||
|
||||
//Basically NSOutlineViewDelegate wrapper methods
|
||||
/**
|
||||
@brief Invoked when *notification* is posted (when a deletion key is pressed and a row in the Source List is selected).
|
||||
@discussion This method is invoked when the `PXSLDeleteKeyPressedOnRowsNotification` notification is posted. See `PXSourceListDelegate.h` for documentation for this notification constant.
|
||||
|
||||
@param notification The posted notification.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceListDeleteKeyPressedOnRows:(NSNotification *)notification;
|
||||
|
||||
// The following methods are basically wrappers around NSOutlineViewDelegate methods.
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name View-based Source List Delegate Methods
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns the view used to display the given item.
|
||||
@discussion This method is analagous to `-outlineView:viewForTableColumn:item:` declared on `NSOutlineViewDelegate`, although it doesn't pass an `NSTableColumn` parameter as `PXSourceList` implicitly only uses one table column. See the documentation for `-outlineView:viewForTableColumn:item:` for more information.
|
||||
|
||||
Unlike when using `PXSourceList` in cell-based mode where the icon and badge value for each item can be set up using `PXSourceListDataSource` methods, it is in this method that you should set up the icon and badge for the view (if applicable) when using `PXSourceList` in view-based mode. You can make use of the `PXSourceListTableCellView` class which exposes an outlet for a `PXSourceListBadgeView` (the class included with the project used to display badges), and the `textField` and `imageView` outlets (which are inherited from its superclass, `NSTableCellView`) for the item's label and icon, respectively.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return The view to display for the specified item, or `nil` if you don't want to display a view for the item.
|
||||
|
||||
@warning This is a required method when using the Source List in view-based mode.
|
||||
|
||||
@see sourceList:rowViewForItem:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (NSView *)sourceList:(PXSourceList *)aSourceList viewForItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns the view used to display the given row.
|
||||
@discussion This method is analagous to `-outlineView:rowViewForItem:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return An `NSTableRowView` instance, or `nil` if the Source List should create one and use that instead.
|
||||
|
||||
@see sourceList:viewForItem:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (NSTableRowView *)sourceList:(PXSourceList *)aSourceList rowViewForItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Sent when a row view has been added to the Source List.
|
||||
@discussion This method is analagous to `-outlineView:didAddRowView:forRow:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param rowView The view that was added to the Source List.
|
||||
@param row The row index.
|
||||
|
||||
@see sourceList:didRemoveRowView:forRow:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (void)sourceList:(PXSourceList *)aSourceList didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row;
|
||||
|
||||
/**
|
||||
@brief Sent when a row view has been removed from the Source List.
|
||||
@discussion This method is analagous to `-outlineView:didRemoveRowView:forRow:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param rowView The row view that was removed from the Source List.
|
||||
@param row The row index.
|
||||
|
||||
@see sourceList:didAddRowView:forRow:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (void)sourceList:(PXSourceList *)aSourceList didRemoveRowView:(NSTableRowView *)rowView forRow:(NSInteger)row;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Handling Selection
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns a Boolean value indicating whether a given item should be selected.
|
||||
@discussion This method is analagous to `-outlineView:shouldSelectItem:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` to allow the Source List to select *item*, or `NO` otherwise.
|
||||
|
||||
@see sourceList:selectionIndexesForProposedSelection:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList shouldSelectItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns the indexes that should be selected for a user-initiated selection.
|
||||
@discussion This method is analagous to `-outlineView:selectionIndexesForProposedSelection:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param proposedSelectionIndexes The proposed indexes of rows that should be selected.
|
||||
|
||||
@return An `NSIndexSet` object containing the rows that should be selected in the proposed selection.
|
||||
|
||||
@see sourceList:shouldSelectItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSIndexSet*)sourceList:(PXSourceList*)aSourceList selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes;
|
||||
|
||||
/**
|
||||
@brief Invoked when *notification* is posted (when the Source List's selection changes).
|
||||
@discussion This method is invoked when the `PXSLSelectionIsChangingNotification` notification is posted. See `PXSourceListDelegate.h` for documentation for this notification constant.
|
||||
|
||||
This method is analagous to `-outlineViewSelectionIsChanging:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param notification The posted notification.
|
||||
|
||||
@see sourceListSelectionDidChange:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceListSelectionIsChanging:(NSNotification *)notification;
|
||||
|
||||
/**
|
||||
@brief Invoked when *notification* is posted (when the Source List's selection has finished changing).
|
||||
@discussion This method is invoked when the `PXSLSelectionDidChangeNotification` notification is posted. See `PXSourceListDelegate.h` for documentation for this notification constant.
|
||||
|
||||
This method is analagous to `-outlineViewSelectionDidChange:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param notification The posted notification.
|
||||
|
||||
@see sourceListSelectionIsChanging:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceListSelectionDidChange:(NSNotification *)notification;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Working with Type Selection
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns the string that is used for type selection for a given item.
|
||||
@discussion This method is analagous to `-outlineView:typeSelectStringForTableColumn:item:` declared on `NSOutlineViewDelegate`, although it doesn't pass an `NSTableColumn` parameter as `PXSourceList` implicitly only uses one table column. See the documentation for `-outlineView:typeSelectStringForTableColumn:item:` for more information.
|
||||
|
||||
@param sourceList The Source List that sent the message.
|
||||
@param item The item to generate the type selection string for.
|
||||
|
||||
@return The string value used for type selection of *item*.
|
||||
|
||||
@see sourceList:nextTypeSelectMatchFromItem:toItem:forString:
|
||||
@see sourceList:shouldTypeSelectForEvent:withCurrentSearchString:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (NSString *)sourceList:(PXSourceList *)sourceList typeSelectStringForItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns the first item that matches the given search string from within the given range.
|
||||
@discussion This method is analagous to `-outlineView:nextTypeSelectMatchFromItem:toItem:forString:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param sourceList The Source List that sent the message.
|
||||
@param startItem The first item to search.
|
||||
@param endItem The item before which to stop searching.
|
||||
@param searchString The string to search.
|
||||
|
||||
@return The first item in the *startItem*--*endItem* range which matches *searchString*, or `nil` if there is no match.
|
||||
|
||||
@see sourceList:typeSelectStringForItem:
|
||||
@see sourceList:shouldTypeSelectForEvent:withCurrentSearchString:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (id)sourceList:(PXSourceList *)sourceList nextTypeSelectMatchFromItem:(id)startItem toItem:(id)endItem forString:(NSString *)searchString;
|
||||
|
||||
/**
|
||||
@brief Returns a Boolean value which indicates whether type select should proceed for a given event and search string.
|
||||
@discussion This method is analagous to `-outlineView:shouldTypeSelectForEvent:withCurrentSearchString:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param sourceList The Source List that sent the message.
|
||||
@param event The event that caused this message to be sent.
|
||||
@param searchString The search string for which searching is to proceed from.
|
||||
|
||||
@return `YES` if type select should proceed, or `NO` otherwise.
|
||||
|
||||
@see sourceList:typeSelectStringForItem:
|
||||
@see sourceList:nextTypeSelectMatchFromItem:toItem:forString:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList *)sourceList shouldTypeSelectForEvent:(NSEvent *)event withCurrentSearchString:(NSString *)searchString;
|
||||
|
||||
/**
|
||||
@brief Returns a Boolean value which indicates whether a cell expansion tooltip should be displayed for a given item.
|
||||
@discussion This method is analagous to `-outlineView:shouldShowCellExpansionForTableColumn:item:` declared on `NSOutlineViewDelegate`, although it doesn't pass an `NSTableColumn` parameter as `PXSourceList` implicitly only uses one table column. See the documentation for `-outlineView:shouldShowCellExpansionForItem:` for more information.
|
||||
|
||||
@param sourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` to allow an expansion tooltip to be displayed for *item*, otherwise `NO`.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, this method is not called.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList *)sourceList shouldShowCellExpansionForItem:(id)item;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Providing Tooltips
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns the tooltip string that should be displayed for a given cell.
|
||||
@discussion This method is analagous to `-outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:` declared on `NSOutlineViewDelegate`, although it doesn't pass an `NSTableColumn` parameter as `PXSourceList` implicitly only uses one table column. See the documentation for `-outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:` for more information.
|
||||
|
||||
@param sourceList The Source List that sent the message.
|
||||
@param cell The cell to return the tooltip for.
|
||||
@param rect The proposed active area of the tooltip.
|
||||
@param item The item in the data source to display the tooltip for.
|
||||
@param mouseLocation The current mouse location in view coordinates.
|
||||
|
||||
@return The tooltip string to be displayed for *cell*, or `nil` if no tooltip is to be shown.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, this method is not called.
|
||||
|
||||
@since Requires PXSourceList 2.0.0 or above and the OS X v10.7 SDK or above.
|
||||
*/
|
||||
- (NSString *)sourceList:(PXSourceList *)sourceList toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect item:(id)item mouseLocation:(NSPoint)mouseLocation;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Editing Items
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns a Boolean value which indicates whether the Source List should allow editing of a given item.
|
||||
@discussion This method is analagous to `-outlineView:shouldEditTableColumn:item:` declared on `NSOutlineViewDelegate`, although it doesn't pass an `NSTableColumn` parameter as `PXSourceList` implicitly only uses one table column. See the documentation for `-outlineView:shouldEditTableColumn:item:` for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` to allow editing of *item*, or `NO` otherwise.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList shouldEditItem:(id)item;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Customising Tracking Support
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns a Boolean value that indicates whether a given cell should be tracked
|
||||
@discussion This method is analagous to `-outlineView:shouldTrackCell:forTableColumn:item:` declared on `NSOutlineViewDelegate`, although it doesn't pass an `NSTableColumn` parameter as `PXSourceList` implicitly only uses one table column. See the documentation for `-outlineView:shouldTrackCell:forTableColumn:item:` for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param cell The cell used to display *item*.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` if the cell should be tracked for *item*, otherwise `NO`.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, this method is not called.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList shouldTrackCell:(NSCell *)cell forItem:(id)item;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Expanding and Collapsing the Outline
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns a Boolean value that indicates whether a given item should be expanded.
|
||||
@discussion This method is analagous to `-outlineView:shouldExpandItem:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` to allow expansion of *item*, otherwise `NO`.
|
||||
|
||||
@see sourceListItemWillExpand:
|
||||
@see sourceListItemDidExpand:
|
||||
@see sourceList:shouldCollapseItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList shouldExpandItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns a Boolean value that indicates whether a given item should be collapsed.
|
||||
@discussion This method is analagous to `-outlineView:shouldCollapseItem:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return `YES` to allow *item* to be collapsed, otherwise `NO`.
|
||||
|
||||
@see sourceListItemWillCollapse:
|
||||
@see sourceListItemDidCollapse:
|
||||
@see sourceList:shouldExpandItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList shouldCollapseItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Invoked when *notification* is posted (when an item in the Source List is about to expand in response to user input).
|
||||
@discussion This method is invoked when the `PXSLItemWillExpandNotification` notification is posted. See `PXSourceListDelegate.h` for documentation for this notification constant.
|
||||
|
||||
This method is analagous to `-outlineViewItemWillExpand:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param notification The posted notification.
|
||||
|
||||
@see sourceListItemDidExpand:
|
||||
@see sourceList:shouldExpandItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceListItemWillExpand:(NSNotification *)notification;
|
||||
|
||||
/**
|
||||
@brief Invoked when *notification* is posted (when an item in the Source List was expanded in response to user input).
|
||||
@discussion This method is invoked when the `PXSLItemDidExpandNotification` notification is posted. See `PXSourceListDelegate.h` for documentation for this notification constant.
|
||||
|
||||
This method is analagous to `-outlineViewItemDidExpand:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param notification The posted notification.
|
||||
|
||||
@see sourceListItemWillExpand:
|
||||
@see sourceList:shouldExpandItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceListItemDidExpand:(NSNotification *)notification;
|
||||
|
||||
/**
|
||||
@brief Invoked when *notification* is posted (when an item in the Source List is about to collapse in response to user input).
|
||||
@discussion This method is invoked when the `PXSLItemWillCollapseNotification` notification is posted. See `PXSourceListDelegate.h` for documentation for this notification constant.
|
||||
|
||||
This method is analagous to `-outlineViewItemWillCollapse:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param notification The posted notification.
|
||||
|
||||
@see sourceListItemDidCollapse:
|
||||
@see sourceList:shouldCollapseItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceListItemWillCollapse:(NSNotification *)notification;
|
||||
|
||||
/**
|
||||
@brief Invoked when *notification* is posted (when an item in the Source List was collapsed in response to user input).
|
||||
@discussion This method is invoked when the `PXSLItemDidCollapseNotification` notification is posted. See `PXSourceListDelegate.h` for documentation for this notification constant.
|
||||
|
||||
This method is analagous to `-outlineViewItemDidCollapse:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param notification The posted notification.
|
||||
|
||||
@see sourceListItemWillCollapse:
|
||||
@see sourceList:shouldCollapseItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceListItemDidCollapse:(NSNotification *)notification;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Customising Row Sizes
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns the height in points of the row for the given item.
|
||||
@discussion This method is analagous to `-outlineView:heightOfRowByItem:` declared on `NSOutlineViewDelegate`. See the documentation for this method for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return The height of the row used to display *item* in points.
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (CGFloat)sourceList:(PXSourceList*)aSourceList heightOfRowByItem:(id)item;
|
||||
|
||||
- (NSCell*)sourceList:(PXSourceList*)aSourceList willDisplayCell:(id)cell forItem:(id)item;
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Displaying Cells
|
||||
///---------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@brief Informs the delegate that the Source List is about to display the cell associated with the given item.
|
||||
@discussion This method is analagous to `-outlineView:willDisplayCell:forTableColumn:item:` declared on `NSOutlineViewDelegate`, although it doesn't pass an `NSTableColumn` parameter as `PXSourceList` implicitly only uses one table column. See the documentation for `-outlineView:willDisplayCell:forTableColumn:item:` for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param cell The cell about to be displayed.
|
||||
@param item An item in the data source.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, this method is not called.
|
||||
|
||||
@see sourceList:dataCellForItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (void)sourceList:(PXSourceList*)aSourceList willDisplayCell:(id)cell forItem:(id)item;
|
||||
|
||||
/**
|
||||
@brief Returns the cell for use with a given item in the Source List.
|
||||
@discussion This method is analagous to `-outlineView:dataCellForTableColumn:item:` declared on `NSOutlineViewDelegate`, although it doesn't pass an `NSTableColumn` parameter as `PXSourceList` implicitly only uses one table column. See the documentation for `-outlineView:dataCellForTableColumn:item:` for more information.
|
||||
|
||||
@param aSourceList The Source List that sent the message.
|
||||
@param item An item in the data source.
|
||||
|
||||
@return The cell used to display *item*.
|
||||
|
||||
@warning This method is only used by the Source List when operating in cell-based mode. When the Source List is operating in view-based mode, this method is not called.
|
||||
|
||||
@see sourceList:willDisplayCell:forItem:
|
||||
|
||||
@since Requires PXSourceList 0.8 or above and the OS X v10.5 SDK or above.
|
||||
*/
|
||||
- (NSCell*)sourceList:(PXSourceList*)aSourceList dataCellForItem:(id)item;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSObject (PXSourceListNotifications)
|
||||
|
||||
//Selection
|
||||
- (void)sourceListSelectionIsChanging:(NSNotification *)notification;
|
||||
- (void)sourceListSelectionDidChange:(NSNotification *)notification;
|
||||
|
||||
//Item expanding/collapsing
|
||||
- (void)sourceListItemWillExpand:(NSNotification *)notification;
|
||||
- (void)sourceListItemDidExpand:(NSNotification *)notification;
|
||||
- (void)sourceListItemWillCollapse:(NSNotification *)notification;
|
||||
- (void)sourceListItemDidCollapse:(NSNotification *)notification;
|
||||
|
||||
- (void)sourceListDeleteKeyPressedOnRows:(NSNotification *)notification;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
//PXSourceList delegate notifications
|
||||
/**
|
||||
@brief This is analagous to the `NSOutlineViewSelectionIsChangingNotification` notification. Take a look at the `NSOutlineView` documentation for more information.
|
||||
@since Requires PXSourceList 0.8 or above.
|
||||
*/
|
||||
extern NSString * const PXSLSelectionIsChangingNotification;
|
||||
extern NSString * const PXSLSelectionDidChangeNotification;
|
||||
extern NSString * const PXSLItemWillExpandNotification;
|
||||
extern NSString * const PXSLItemDidExpandNotification;
|
||||
extern NSString * const PXSLItemWillCollapseNotification;
|
||||
extern NSString * const PXSLItemDidCollapseNotification;
|
||||
extern NSString * const PXSLDeleteKeyPressedOnRowsNotification;
|
||||
|
||||
/**
|
||||
@brief This is analagous to the `NSOutlineViewSelectionDidChangeNotification` notification. Take a look at the `NSOutlineView` documentation for more information.
|
||||
@since Requires PXSourceList 0.8 or above.
|
||||
*/
|
||||
extern NSString * const PXSLSelectionDidChangeNotification;
|
||||
|
||||
/**
|
||||
@brief This is analagous to the `NSOutlineViewItemWillExpandNotification` notification. Take a look at the `NSOutlineView` documentation for more information.
|
||||
@since Requires PXSourceList 0.8 or above.
|
||||
*/
|
||||
extern NSString * const PXSLItemWillExpandNotification;
|
||||
|
||||
/**
|
||||
@brief This is analagous to the `NSOutlineViewItemDidExpandNotification` notification. Take a look at the `NSOutlineView` documentation for more information.
|
||||
@since Requires PXSourceList 0.8 or above.
|
||||
*/
|
||||
extern NSString * const PXSLItemDidExpandNotification;
|
||||
|
||||
/**
|
||||
@brief This is analagous to the `NSOutlineViewItemWillCollapseNotification` notification. Take a look at the `NSOutlineView` documentation for more information.
|
||||
@since Requires PXSourceList 0.8 or above.
|
||||
*/
|
||||
extern NSString * const PXSLItemWillCollapseNotification;
|
||||
|
||||
/**
|
||||
@brief This is analagous to the `NSOutlineViewItemDidCollapseNotification` notification. Take a look at the `NSOutlineView` documentation for more information.
|
||||
@since Requires PXSourceList 0.8 or above.
|
||||
*/
|
||||
extern NSString * const PXSLItemDidCollapseNotification;
|
||||
|
||||
/**
|
||||
@brief Posted whenever a "deletion key" (backspace, cmd-backspace or fn-backspace) is pressed and handled by the Source List and a row is selected.
|
||||
@discussion The notification *object* is the `PXSourceList` object which the notification was posted by. The *userInfo* dictionary contains a `@"rows"` key which maps to an `NSIndexSet` object which contains the selected row indexes that were selected when the notification was posted.
|
||||
@since Requires PXSourceList 0.8 or above.
|
||||
*/
|
||||
extern NSString * const PXSLDeleteKeyPressedOnRowsNotification;
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
//
|
||||
// PXSourceListItem.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 08/01/2014.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
|
||||
`PXSourceListItem` is a generic `NSObject` subclass which can be used to build a hierarchical model for use by
|
||||
a `PXSourceList` data source.
|
||||
|
||||
@warning While it is not mandatory to use `PXSourceListItem` objects in a `PXSourceList` data source, this
|
||||
class is generic enough that it should serve most use cases.
|
||||
|
||||
@discussion ### Basic properties
|
||||
|
||||
`PXSourceListItem` has been designed to contain properties for the frequently-used information which you need
|
||||
from a Source List data source item when implementing the `PXSourceListDataSource` (and possibly
|
||||
`PXSourceListDelegate`) methods, namely:
|
||||
|
||||
* The title displayed in the Source List for the given item.
|
||||
* The icon displayed to the left of the given item in the Source List.
|
||||
* The badge value displayed to the right of the given item in the Source List.
|
||||
* Child items of the given item.
|
||||
|
||||
The existence of these core properties means that it is unlikely that you should have to create your own
|
||||
`PXSourceListItem` subclass.
|
||||
|
||||
### Identifying objects
|
||||
|
||||
`PXSourceListItem`s are often backed by data model objects that are used in other parts of your application, and
|
||||
the API has been designed to be able to easily identify a given model object from any part of your code
|
||||
given an arbitrary `PXSourceListItem`. This is useful when you obtain an item using one of `PXSourceList`'s methods
|
||||
or are given one as an argument to a `PXSourceListDelegate` or `PXSourceListDataSource` protocol method and you
|
||||
need to find its backing data model object to be able to use in application logic.
|
||||
|
||||
There are two (often distinct) patterns used to identify a given backing model object in a `PXSourceListItem`
|
||||
object:
|
||||
|
||||
* Using the `identifier` property. This is probably the easiest way of identifying items, and these identifiers
|
||||
are best defined as string constants which you can reference from multiple places in your code.
|
||||
* Using the `representedObject` property. Using `representedObject` can be useful if the underlying model
|
||||
object has identifying information about it which you can use when determining which object you're
|
||||
working with given a `PXSourceListItem` instance.
|
||||
|
||||
*/
|
||||
@interface PXSourceListItem : NSObject
|
||||
|
||||
@property (strong, nonatomic) NSString *title;
|
||||
@property (strong, nonatomic) NSImage *icon;
|
||||
@property (weak, nonatomic) id representedObject;
|
||||
@property (strong, nonatomic) NSString *identifier;
|
||||
@property (strong, nonatomic) NSNumber *badgeValue;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Convenience initialisers
|
||||
///---------------------------------------------------------------------------------------
|
||||
/** Creates and returns an item with the given parameters.
|
||||
|
||||
@param title A title.
|
||||
@param identifier An identifier.
|
||||
|
||||
@return An item initialised with the given parameters.
|
||||
|
||||
@see itemWithTitle:identifier:icon:
|
||||
@see itemWithRepresentedObject:icon:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
+ (instancetype)itemWithTitle:(NSString *)title identifier:(NSString *)identifier;
|
||||
|
||||
/** Creates and returns an item with the given parameters.
|
||||
|
||||
@param title A title.
|
||||
@param identifier An identifier.
|
||||
@param icon An icon.
|
||||
|
||||
@return An item initialised with the given parameters.
|
||||
|
||||
@see itemWithTitle:identifier:
|
||||
@see itemWithRepresentedObject:icon:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
+ (instancetype)itemWithTitle:(NSString *)title identifier:(NSString *)identifier icon:(NSImage *)icon;
|
||||
|
||||
/** Creates and returns an item with the given parameters.
|
||||
|
||||
@param object An object.
|
||||
@param icon An icon.
|
||||
|
||||
@return An item initialised with the given parameters.
|
||||
|
||||
@see itemWithTitle:identifier:
|
||||
@see itemWithTitle:identifier:icon:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
+ (instancetype)itemWithRepresentedObject:(id)object icon:(NSImage *)icon;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Working with child items
|
||||
///---------------------------------------------------------------------------------------
|
||||
/**
|
||||
@brief Returns the receiver's children.
|
||||
|
||||
@warning This property is backed by an `NSMutableArray` since an item's children *are* mutable. The getter for
|
||||
this property returns a copied array for safety, so this getter should not be called excessively.
|
||||
|
||||
@see hasChildren
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
@property (strong, nonatomic) NSArray *children;
|
||||
|
||||
/**
|
||||
@brief Returns whether the receiver has any child items.
|
||||
@discussion This is faster than calling `-children` on the receiver then checking the number of items in the array
|
||||
because of how this getter is implemented. See `-children` for more information.
|
||||
|
||||
@see children
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
- (BOOL)hasChildren;
|
||||
|
||||
/**
|
||||
@brief Adds an item to the receiver's array of child items.
|
||||
@discussion Adds *item* to the end of the receiver's array of child items.
|
||||
|
||||
This is a convenience method rather than having to call `-children` on the receiver, create a mutable copy
|
||||
and then mutate this array before setting it back on the receiver.
|
||||
|
||||
@param childItem An item
|
||||
|
||||
@see insertChildItem:atIndex:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
- (void)addChildItem:(PXSourceListItem *)childItem;
|
||||
|
||||
/**
|
||||
@brief Inserts an item to the receiver's array of child items at a given index.
|
||||
@discussion Inserts *item* at *index* in the receiver's array of child items.
|
||||
|
||||
This is a convenience method rather than having to call `-children` on the receiver, create a mutable copy
|
||||
and then mutate this array before setting it back on the receiver.
|
||||
|
||||
@param childItem An item
|
||||
@param index An index
|
||||
|
||||
@see addChildItem:
|
||||
@see insertChildItems:atIndexes:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
- (void)insertChildItem:(PXSourceListItem *)childItem atIndex:(NSUInteger)index;
|
||||
|
||||
/**
|
||||
@brief Removes an item from the receiver's array of child items.
|
||||
@discussion Removes *item* from the receiver's array of child items.
|
||||
|
||||
This is a convenience method rather than having to call `-children` on the receiver, create a mutable copy
|
||||
and then mutate this array before setting it back on the receiver.
|
||||
|
||||
@param childItem An item
|
||||
|
||||
@see removeChildItemAtIndex:
|
||||
@see removeChildItems:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
- (void)removeChildItem:(PXSourceListItem *)childItem;
|
||||
|
||||
/**
|
||||
@brief Removes the item at the given index from the receiver's array of child items.
|
||||
@discussion Removes the item at the given *index* from the receiver's array of child items.
|
||||
|
||||
This is a convenience method rather than having to call `-children` on the receiver, create a mutable copy
|
||||
and then mutate this array before setting it back on the receiver.
|
||||
|
||||
@param index An integer representing an index in the receiver's array of children
|
||||
|
||||
@see removeChildItem:
|
||||
@see removeChildItems:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
- (void)removeChildItemAtIndex:(NSUInteger)index;
|
||||
|
||||
/**
|
||||
@brief Removes the items in the given array from the receiver's array of child items.
|
||||
@discussion Removes all of the items in *items* from the receiver's array of children.
|
||||
|
||||
This is a convenience method rather than having to call `-children` on the receiver, create a mutable copy
|
||||
and then mutate this array before setting it back on the receiver.
|
||||
|
||||
@param items An array of `PXSourceListItem` objects
|
||||
|
||||
@see removeChildItem:
|
||||
@see removeChildItemAtIndex:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
- (void)removeChildItems:(NSArray *)items;
|
||||
|
||||
/**
|
||||
@brief Inserts the given items into the receiver's array of child items at the given indexes.
|
||||
@discussion Inserts all of the items in *items* to the receiver's array of children at the given *indexes*.
|
||||
|
||||
This is a convenience method rather than having to call `-children` on the receiver, create a mutable copy
|
||||
and then mutate this array before setting it back on the receiver.
|
||||
|
||||
@param items An array of `PXSourceListItem` objects
|
||||
@param indexes The indexes to insert the child items at
|
||||
|
||||
@see insertChildItem:atIndex:
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
- (void)insertChildItems:(NSArray *)items atIndexes:(NSIndexSet *)indexes;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// PXSourceListItem.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 08/01/2014.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "PXSourceListItem.h"
|
||||
|
||||
@implementation PXSourceListItem {
|
||||
NSMutableArray *_children;
|
||||
}
|
||||
|
||||
+ (instancetype)itemWithTitle:(NSString *)title identifier:(NSString *)identifier
|
||||
{
|
||||
return [self itemWithTitle:title identifier:identifier icon:nil];
|
||||
}
|
||||
|
||||
+ (instancetype)itemWithTitle:(NSString *)title identifier:(NSString *)identifier icon:(NSImage *)icon
|
||||
{
|
||||
PXSourceListItem *item = [[self alloc] init];
|
||||
|
||||
item.title = title;
|
||||
item.identifier = identifier;
|
||||
item.icon = icon;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
+ (instancetype)itemWithRepresentedObject:(id)object icon:(NSImage *)icon
|
||||
{
|
||||
PXSourceListItem *item = [[self alloc] init];
|
||||
|
||||
item.representedObject = object;
|
||||
item.icon = icon;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_children = [[NSMutableArray alloc] init];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Custom Accessors
|
||||
|
||||
- (NSArray *)children
|
||||
{
|
||||
return [_children copy];
|
||||
}
|
||||
|
||||
- (void)setChildren:(NSArray *)children
|
||||
{
|
||||
_children = [children mutableCopy];
|
||||
}
|
||||
|
||||
#pragma mark - Child Convenience Methods
|
||||
|
||||
- (BOOL)hasChildren
|
||||
{
|
||||
return _children.count > 0;
|
||||
}
|
||||
|
||||
- (void)addChildItem:(PXSourceListItem *)childItem
|
||||
{
|
||||
[_children addObject:childItem];
|
||||
}
|
||||
|
||||
- (void)insertChildItem:(PXSourceListItem *)childItem atIndex:(NSUInteger)index
|
||||
{
|
||||
[_children insertObject:childItem atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeChildItem:(PXSourceListItem *)childItem
|
||||
{
|
||||
[_children removeObject:childItem];
|
||||
}
|
||||
|
||||
- (void)removeChildItemAtIndex:(NSUInteger)index
|
||||
{
|
||||
[_children removeObjectAtIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeChildItems:(NSArray *)items
|
||||
{
|
||||
[_children removeObjectsInArray:items];
|
||||
}
|
||||
|
||||
- (void)insertChildItems:(NSArray *)items atIndexes:(NSIndexSet *)indexes
|
||||
{
|
||||
[_children insertObjects:items atIndexes:indexes];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// PXSourceListTableCellView.h
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 31/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class PXSourceListBadgeView;
|
||||
|
||||
/**
|
||||
`PXSourceListTableCellView` is an `NSTableCellView` subclass which can be used when using `PXSourceList`
|
||||
in view-based mode.
|
||||
|
||||
Similar to `NSTableCellView` and its `textField` and `imageView` outlets, `PXSourceListTableCellView`
|
||||
provides a `badgeView` outlet which can be hooked up to a `PXSourceListBadgeView` in Interface Builder
|
||||
and then configured in `sourceList:viewForItem:`.
|
||||
|
||||
`PXSourceListTableCellView` positions its `badgeView` automatically (as `NSTableCellView` does for the `textField`
|
||||
and `imageView` outlets) to be positioned centred (vertically) and rightmost (horizontally) within the table cell's
|
||||
bounds. If you want to change this positioning you can do so by creating a `PXSourceListTableCellView` subclass and
|
||||
overriding `-layout`, but note that idiomatically, source lists display badges to the right of each row.
|
||||
*/
|
||||
@interface PXSourceListTableCellView : NSTableCellView
|
||||
|
||||
/**
|
||||
@brief The badge view displayed by the cell.
|
||||
@discussion When a `PXSourceListTableCellView` instance is created, a `PXSourceListTableCellView` instance
|
||||
is *not* automatically created and set to this property (just like with `NSTableCellView` and its
|
||||
`textField` and `imageView` properties). This property is purely declared on this class to make creating
|
||||
table cell views for a `PXSourceList` in Interface Builder easier without having to declare your own
|
||||
`NSTableCellView` subclass.
|
||||
|
||||
This property is typically configured in the `PXSourceListDelegate` method `sourceList:viewForItem:`.
|
||||
|
||||
@since Requires PXSourceList 2.0.0 and above and the Mac OS X 10.7 SDK or above.
|
||||
*/
|
||||
@property (weak, nonatomic) IBOutlet PXSourceListBadgeView *badgeView;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// PXSourceListTableCellView.m
|
||||
// PXSourceList
|
||||
//
|
||||
// Created by Alex Rozanski on 31/12/2013.
|
||||
// Copyright 2009-14 Alex Rozanski http://alexrozanski.com and other contributors.
|
||||
// This software is licensed under the New BSD License. Full details can be found in the README.
|
||||
//
|
||||
|
||||
#import "PXSourceListTableCellView.h"
|
||||
#import "PXSourceListBadgeView.h"
|
||||
|
||||
@implementation PXSourceListTableCellView
|
||||
|
||||
- (void)layout
|
||||
{
|
||||
[super layout];
|
||||
|
||||
if (!self.badgeView)
|
||||
return;
|
||||
|
||||
[self.badgeView sizeToFit];
|
||||
|
||||
NSRect bounds = self.bounds;
|
||||
NSSize badgeSize = self.badgeView.frame.size;
|
||||
self.badgeView.frame = NSMakeRect(NSMaxX(bounds) - badgeSize.width,
|
||||
NSMidY(bounds) - round(badgeSize.height / 2.0f),
|
||||
badgeSize.width, badgeSize.height);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,65 +1,146 @@
|
||||
#PXSourceList
|
||||
|
||||
A Source List control for use with the Mac OS X 10.5 SDK or above.
|
||||
`PXSourceList` is an `NSOutlineView` subclass used for easily implementing source lists in your applications.
|
||||
|
||||
[Download the documentation][1]
|
||||
PXSourceList requires the OS X 10.7 SDK and above and is licensed under the New BSD License.
|
||||
|
||||
`PXSourceList` is licensed under the New BSD License.
|
||||

|
||||
|
||||
##Intention
|
||||
[Source Lists][2] are used in a lot of Mac OS X applications, but the support for such controls is quite primitive – at best you create an Outline View with Source List highlighting, but none of the features such as badging are built in by default. `PXSourceList` is a reusable control – within the context of Source Lists – which makes creating applications with Source Lists a much easier process.
|
||||
## Overview
|
||||
Using a [source list](http://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/AppleHIGuidelines/Windows/Windows.html#//apple_ref/doc/uid/20000961-CHDDIGDE) for navigation is a common user interface paradigm in OS X applications, but requires a fair amount of manual set up and customisation of standard Cocoa controls.
|
||||
|
||||
##Using the code
|
||||
There are only a few steps involved:
|
||||
**PXSourceList subclasses NSOutlineView and provides much of the common styling and idiomatic behaviour of source lists for you through a clean and simple API.**
|
||||
|
||||
1. Download the source, and copy `PXSourceList.h`, `PXSourceList.m`, `PXSourceListDelegate.h` and `PXSourceListDataSource.h` into your Xcode project.
|
||||
2. To create the control in Interface Builder, drag an `NSOutlineView` object over to a window and in the Identity Inspector for the Outline View, change the class to `PXSourceList`. In the Attributes Inspector, set it to have only 1 column, uncheck "Headers" in the "Columns" section and set "Highlight" to "Source List" – there is an NIB in the example project bundled with the source.
|
||||
3. Make sure to `#import "PXSourceList.h"` for files that require it (the delegate and data source protocol files are imported in this main header), and ensure that your class(es) that are the `delegate` and/or `dataSource` for the Source List conform to the `PXSourceListDelegate` and `PXSourceListDataSource` protocols respectively.
|
||||
PXSourceList has several key features:
|
||||
|
||||
**Note:** If you intend to use PXSourceList with the 10.5 SDK, you will need to remove some of the protocols that PXSourceList conforms to which do not exist – in `PXSourceList.h`, remove the `<NSOutlineViewDelegate, NSOutlineViewDataSource, NSMenuDelegate>` from the interface declaration.
|
||||
- Built-in support for displaying badges — blue-grey pills which display numerical values such as the number of photos in a particular album.
|
||||
- Always displaying root-level items with ‘group styling’ — the blue-grey uppercase text seen in the source lists in apps such as Mail.app. This requires no extra configuration.
|
||||
- Support for displaying specific groups as ‘always expanded’ through implementation of a single delegate method. These groups will always show their child items and won’t show a Show/Hide button on hover.
|
||||
- Since idiomatic source lists use only a single column and don’t display column headers, PXSourceList operates with only a single table column and doesn’t display a header. This is reflected in PXSourceList’s API and makes the control easier to use.
|
||||
- The project includes a generic data model class which can be used for building a data source data model without having to roll your own.
|
||||
|
||||
There is also an example project bundled with the source to see how the control is used.
|
||||
Note that [in the OS X Human Interface Guidelines](https://developer.apple.com/library/mac/documentation/userexperience/conceptual/applehiguidelines/Windows/Windows.html#//apple_ref/doc/uid/20000961-CHDDIGDE), source lists are broken down into those which provide navigation for the app as a whole (and have a blue-grey background), and those which provide selection functionality for the window (with a white background). PXSourceList implements this *first* style of source list; the second type doesn’t require quite as much common customisation so would not be useful as a standalone control.
|
||||
|
||||
##Screenshots
|
||||
![alt text][3]
|
||||
## Using PXSourceList
|
||||
|
||||
##How the control works
|
||||
I have tried to structure PXSourceList in a way such that it fits common Cocoa design patterns and therefore makes it easier to use.
|
||||
### Installing with Cocoapods
|
||||
|
||||
PXSourceList adapts the delegate and data source design patterns, and extends those of the `NSOutlineViewDelegate` and `NSOutlineViewDataSource`, much in the way that these extend the appropriate `NSTableView` protocols.
|
||||
You can install PXSourceList by adding the following line to your `Podfile`:
|
||||
|
||||
If you want more information have a look at the [Outline View Programming Topics for Cocoa][4] – the Source List delegate and data source implementation work in much the same way, but with methods added and removed, as detailed in the documentation.
|
||||
pod 'PXSourceList', '~> 2.0'
|
||||
|
||||
##Documentation
|
||||
Documentation is available for PXSourceList, downloadable [here][5]. Provided in the ZIP file is a folder containing HTML documentation, or a docset which can be opened in Xcode and which is then searchable from the Xcode Developer Documentation.
|
||||
### Cloning with git
|
||||
|
||||
If you feel that any areas of the documentation are lacking or missing, please feel free to [let me know][6], which will be much appreciated.
|
||||
You can also get the source by cloning with git:
|
||||
|
||||
**Note:** the documentation for the Source List notifications can be found in the `NSObject(PXSourceListNotifications)` reference, which is linked to from the documentation index page.
|
||||
$ git clone https://github.com/Perspx/PXSourceList.git
|
||||
|
||||
###Documentation Revision History
|
||||
For the latest documentation see the PXSourceList [downloads page][7].
|
||||
You can then either:
|
||||
|
||||
##Known Issues
|
||||
* Copy all of the files from the `PXSourceList` directory (including those in the `Internal` subdirectory) into your project
|
||||
|
||||
- Calling `delegate` or `dataSource` on the Source List returns the Source List instance. This is, unfortunately, a side effect of how delegate and data source methods are handled within the Source List – I hope to work around it in the future.
|
||||
- No bindings implementation (yet).
|
||||
***or***
|
||||
|
||||
##Attribution
|
||||
* Add the Xcode project as a subproject to your own Xcode project or to your workspace and link against the `PXSourceList` framework target.
|
||||
|
||||
I was spurred along the way by many sources, but in particular [BWToolkit][8] by Brandon Walkin and Fraser Kuyvenhoven, which gave me the idea of how to handle the Source List delegate and data source methods.
|
||||
### Using PXSourceList in your application
|
||||
|
||||
Also Brian Dunagan's post on [Source List badging][9] and determining state for the various colours was a great help when I came to the drawing code for that.
|
||||
1. Drag an `NSOutlineView` object into the window/view that you're displaying the source list in. Often source lists are placed in the leftmost panel of an `NSSplitView`.
|
||||
2. In the Identity inspector for the outline view, change the class from the `NSOutlineView` placeholder to `PXSourceList`.
|
||||
3. With the *source list* selected (it helps to use Interface Builder’s *Document Outline* view for this), select "Source List" for the "Highlight" attribute under the "Table View" section in the Attributes inspector.
|
||||
4. Control-click on the Source List and drag connectors to the object(s) that you want to be your Source List's delegate and data source, selecting "delegate" or "dataSource" respectively from the popup menu that is shown when you release the mouse button. A Source List *requires* a data source object, but having a delegate is optional.
|
||||
5. Make sure to `#import "PXSourceList.h"` for files that require it (the delegate and data source protocol files are imported in this main header), and ensure that your source list delegate and data source class(es) conform to the `PXSourceListDelegate` and `PXSourceListDataSource` protocols respectively.
|
||||
|
||||
The documentation was created using [Doxygen][10] and [appledoc][11], thanks of which go to the developers of both.
|
||||
There are also two example projects included in the project to see how PXSourceList should be used.
|
||||
|
||||
The icons used in the demo project bundled with the source code are from the [Fugue icon set][12] by Yusuke Kamiyamane.
|
||||
### Cell-based vs. View-based mode
|
||||
As an `NSOutlineView` subclass, PXSourceList can display its contents using cells (in *cell-based* mode) or views (in *view-based* mode). Some delegate and data source methods (see below) are only applicable when PXSourceList is used in cell-based mode, and is noted as such in the documentation.
|
||||
|
||||
##License
|
||||
PXSourceList is licensed under the New BSD License, as detailed below (adapted from OSI http://www.opensource.org/licenses/bsd-license.php):
|
||||
## Documentation
|
||||
`PXSourceList` and its related classes and protocols are documented in the header files included in the repository using [appledoc](http://gentlebytes.com/appledoc/)-style documentation.
|
||||
|
||||
Documentation (in HTML and docset formats) can be generated by building the *Documentation* target from the Xcode project. The resulting documentation will be placed in `docs` in the root directory of the project. To generate documentation in this way, appledoc [must be installed](https://github.com/tomaz/appledoc#quick-install) and the script which builds the documentation expects it to be installed under `/usr/local/bin`.
|
||||
|
||||
If you notice any mistakes or feel that any areas of the documentation are lacking or missing, please [file a GitHub issue](https://github.com/Perspx/PXSourceList/issues).
|
||||
|
||||
## PXSourceList 2
|
||||
PXSourceList 2 is a great improvement over PXSourceList 0.x and 1.x that adds view-based table support and many other small improvements and bugfixes.
|
||||
|
||||
For view-based table support, new delegate and data source methods have been added to bring PXSourceList on-par with `NSOutlineView`’s API, and a generic badge view and `NSTableCellView` subclass have been implemented to allow easy setup of `NSTableCellView`s with PXSourceList.
|
||||
|
||||
Additionally, a generic `PXSourceListItem` class has been implemented for building a data source model without having to roll your own class. A new internal implementation of PXSourceList fixes problems in prior versions where some source list delegate and data source methods weren’t being called.
|
||||
|
||||
Take a look at the [Release Notes](ReleaseNotes.md) for a comprehensive list of changes as well as API changes in version 2.
|
||||
|
||||
## Delegate and Data Source Objects
|
||||
Like `NSOutlineView`, `PXSourceList` objects obtain their content and other information from their *data source* and *delegate* objects using methods defined in the `PXSourceListDataSource` and `PXSourceListDelegate` protocols respectively.
|
||||
|
||||
As well as declaring new delegate and data source methods, since `PXSourceList` subclasses `NSOutlineView`, `PXSourceListDataSource` and `PXSourceListDelegate` include most `NSOutlineViewDelegate` and `NSOutlineViewDataSource` methods but with the "outlineView" prefix replaced with "sourceList". For more information on implementing a data source object, take a look at *[Outline View Programming Topics](https://developer.apple.com/library/mac/documentation/cocoa/conceptual/OutlineView/Articles/UsingOutlineDataSource.html)* — PXSourceList’s delegate and data source implementation works in a very similar way.
|
||||
|
||||
Note that some of the `NSOutlineView` delegate and data source methods are not relevant to PXSourceList, so they haven't been added to `PXSourceListDelegate` and `PXSourceListDataSource`.
|
||||
|
||||
Note also that because of the way PXSourceList works under the hood, `-[PXSourceList delegate]` and `-[PXSourceList dataSource]` have been marked as unavailable (they return an internal proxy object). You should therefore only use `-setDelegate:` and `-setDataSource:`.
|
||||
|
||||
### Required Methods
|
||||
A PXSourceList data source must implement the following methods:
|
||||
|
||||
- (NSUInteger)sourceList:(PXSourceList*)sourceList numberOfChildrenOfItem:(id)item
|
||||
- (id)sourceList:(PXSourceList*)aSourceList child:(NSUInteger)index ofItem:(id)item
|
||||
- (BOOL)sourceList:(PXSourceList*)aSourceList isItemExpandable:(id)item
|
||||
|
||||
If you are using PXSourceList in cell-based mode, you also need to implement:
|
||||
|
||||
- (id)sourceList:(PXSourceList*)aSourceList objectValueForItem:(id)item
|
||||
|
||||
If you are using PXSourceList in view-based mode, you should implement:
|
||||
|
||||
- (NSView *)sourceList:(PXSourceList *)aSourceList viewForItem:(id)item
|
||||
|
||||
in your **delegate** object class.
|
||||
|
||||
Take a look at both the view-based and cell-based example projects in the repository for more information about implementing PXSourceList delegate and data source objects.
|
||||
|
||||
## View-Based Source Lists
|
||||
As mentioned above, PXSourceList can be used in either cell-based- or view-based mode to display content using cells or views.
|
||||
|
||||
When using PXSourceList in view-based mode, several classes have been included in the project to help with setting up views for each item in the table, which is done in the `PXSourceListDataSource` method, `-sourceList:viewForItem:`.
|
||||
|
||||
### PXSourceListBadgeView
|
||||
This is a view class that draws a badge with a given numeric value. Badges are displayed to the right of rows that show them and are displayed with a grey-blue background when the row containing them is not selected, or a white background otherwise.
|
||||
|
||||
### PXSourceListTableCellView
|
||||
This is an `NSTableCellView` subclass that exposes a `badgeView` outlet that can be hooked up to a `PXSourceListBadgeView` instance in Interface Builder and can then be configured in `-sourceList:viewForItem:`. Like with `NSTableCellView`, `PXSourceListTableCellView` positions its `badgeView` automatically for you.
|
||||
|
||||
## Data Source Model Using PXSourceListItem
|
||||
The generic `PXSourceListItem` class has been added in PXSourceList 2 for creation of a data source model without having to roll your own classes.
|
||||
|
||||
Since `PXSourceListDataSource` works by building up a tree structure of model objects (which maps to the tree-like presentation of the content), `PXSourceListItem` allows you to build up a tree structure of model objects using the `children` property and other convenience methods.
|
||||
|
||||
Each item can have associated with it:
|
||||
- **A title**. Useful for setting the `textField` property of an `NSTableCellView` in `-sourceListForItem:`.
|
||||
- **An icon image**. Useful for setting the image on the `imageView` property of an `NSTableCellView` in `-sourceListForItem:`.
|
||||
- **An identifier**. Useful for identifying a given item when given one as the return value from `PXSourceList` method or as a parameter to a `PXSourceListDelegate` or `PXSourceListDataSource` method.
|
||||
- **A badge value**. Useful to store the badge value for a particular item if it doesn’t have a backing data model object that you pull this value from.
|
||||
|
||||
Additionally, each item has a `representedObject` property associated with it which is useful when you don’t want to set the data on a source list item directly, but instead want to pull it from an associated model object. This means that you don’t have to keep your data model and properties on `PXSourceListItem` in sync.
|
||||
|
||||
## Attribution
|
||||
|
||||
Thanks first of all to the [wonderful people](https://github.com/Perspx/PXSourceList/graphs/contributors) who have contributed to the project and helped in improving the project, fixing bugs and adding new features.
|
||||
|
||||
In the initial release of PXSourceList, I was spurred along the way by many sources, but in particular [BWToolkit](http://brandonwalkin.com/bwtoolkit/) by Brandon Walkin and Fraser Kuyvenhoven, which gave me the idea of how to handle the source list delegate and data source methods.
|
||||
|
||||
Brian Dunagan's post on [Source List badging](http://www.bdunagan.com/2008/11/10/cocoa-tutorial-source-list-badges-part-2/) and determining state for the various colours was also a great help when I came to the drawing code for source list badges.
|
||||
|
||||
The *Documentation* target in the Xcode project makes use of the fantastic [appledoc](http://www.gentlebytes.com/appledoc/), which has been an invaluable tool utilised since the very first version of PXSourceList.
|
||||
|
||||
The icons used in the example projects bundled with the source code are from the [Fugue icon set](http://p.yusukekamiyamane.com) by Yusuke Kamiyamane (in the cell-based example) and the [Mimi Glyphs set](http://salleedesign.com/resources/mimi-glyphs/) by Jeremy Salée (in the view-based example).
|
||||
|
||||
## Licence
|
||||
PXSourceList is licensed under the New BSD License, as detailed below (adapted from OSI [http://www.opensource.org/licenses/bsd-license.php](http://www.opensource.org/licenses/bsd-license.php)):
|
||||
|
||||
|
||||
Copyright © 2011, Alex Rozanski.
|
||||
Copyright © 2009-14, Alex Rozanski and other contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
@@ -69,17 +150,3 @@ Redistribution and use in source and binary forms, with or without modification,
|
||||
- Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
[1]: http://github.com/Perspx/PXSourceList/downloads
|
||||
[2]: http://developer.apple.com/library/mac/#documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGWindows/XHIGWindows.html#//apple_ref/doc/uid/20000961-CHDDIGDE
|
||||
[3]: http://perspx.com/wp-content/uploads/2010/01/pxsourcelist.jpg
|
||||
[4]: http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/OutlineView/Articles/UsingOutlineDataSource.html
|
||||
[5]: http://github.com/Perspx/PXSourceList/downloads
|
||||
[6]: http://perspx.com/contact
|
||||
[7]: http://github.com/Perspx/PXSourceList/downloads
|
||||
[8]: http://brandonwalkin.com/bwtoolkit/
|
||||
[9]: http://www.bdunagan.com/2008/11/10/cocoa-tutorial-source-list-badges-part-2/
|
||||
[10]: http://www.doxygen.org/
|
||||
[11]: http://www.gentlebytes.com/freeware/appledoc/
|
||||
[12]: http://www.pinvoke.com/
|
||||
@@ -0,0 +1,77 @@
|
||||
# PXSourceList Release Notes
|
||||
|
||||
## 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
|
||||
|
||||
- Added support for view-based mode to `PXSourceList`, whilst retaining legacy cell-based support. (View-based delegate methods added are detailed below).
|
||||
- Added a new view-based Source List example target which includes an example of how to use drag-and-drop in the Source List.
|
||||
- Added `PXSourceListTableCellView`, an `NSTableCellView` subclass which is useful when using `PXSourceList` in view-based mode.
|
||||
- Added `PXSourceListBadgeView`, which can be used in `PXSourceListTableCellView`s to display badges. This class's drawing is done by the internal `PXSourceListBadgeCell` class.
|
||||
- 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 shouldn’t 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:`
|
||||
- `-sourceList:didAddRowView:forRow:`
|
||||
- `-sourceList:didRemoveRowView:forRow:`
|
||||
- Added missing `PXSourceListDelegate` methods which map to their `NSOutlineViewDelegate` counterpart methods, namely:
|
||||
- `-sourceList:toolTipForCell:rect:item:mouseLocation:`
|
||||
- `-sourceList:typeSelectStringForItem:`
|
||||
- `-sourceList:nextTypeSelectMatchFromItem:toItem:forString:`
|
||||
- `-sourceList:shouldTypeSelectForEvent:withCurrentSearchString:`
|
||||
- Moved the Source List delegate notification methods that were previously part of an `NSObject` category into `PXSourceListDelegate`. The methods affected are:
|
||||
- `-sourceListSelectionIsChanging:`
|
||||
- `-sourceListSelectionDidChange:`
|
||||
- `-sourceListItemWillExpand:`
|
||||
- `-sourceListItemDidExpand:`
|
||||
- `-sourceListItemWillCollapse:`
|
||||
- `-sourceListItemDidCollapse:`
|
||||
- `-sourceListDeleteKeyPressedOnRows:`
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Fixed a *huge* bug where several delegate methods which weren't being called in version 0.x and 1.x of PXSourceList, by removing explicit implementations of `NSOutlineViewDelegate` methods in `PXSourceList` which are now forwarded using a shiny new proxy-based implementation. The stub method implementations removed from `PXSourceList` are:
|
||||
- `-outlineView:numberOfChildrenOfItem:`
|
||||
- `-outlineView:child:ofItem:`
|
||||
- `-outlineView:isItemExpandable:`
|
||||
- `-outlineView:objectValueForTableColumn:byItem:`
|
||||
- `-outlineView:setObjectValue:forTableColumn:byItem:`
|
||||
- `-outlineView:itemForPersistentObject:`
|
||||
- `-outlineView:persistentObjectForItem:`
|
||||
- `-outlineView:writeItems:toPasteboard:`
|
||||
- `-outlineView:writeItems:toPasteboard:`
|
||||
- `-outlineView:validateDrop:proposedItem:proposedChildIndex:`
|
||||
- `-outlineView:acceptDrop:item:childIndex:`
|
||||
- `-outlineView:namesOfPromisedFilesDroppedAtDestination:forDraggedItems:`
|
||||
- `-outlineView:pasteboardWriterForItem:`
|
||||
- `-outlineView:draggingSession:willBeginAtPoint:forItems:`
|
||||
- `-outlineView:draggingSession:endedAtPoint:operation:`
|
||||
- `-outlineView:updateDraggingItemsForDrag:`
|
||||
- `-outlineView:shouldExpandItem:`
|
||||
- `-outlineView:shouldTrackCell:forTableColumn:item:`
|
||||
- `-outlineView:heightOfRowByItem:`
|
||||
- `-outlineView:selectionIndexesForProposedSelection:`
|
||||
- `-outlineView:dataCellForTableColumn:item:`
|
||||
- `-outlineView:willDisplayCell:forTableColumn:item:`
|
||||
- Fixed the PXSourceList framework's `CFBundleIdentifier`. It should have been `com.alexrozanski.PXSourceList`.
|
||||
|
||||
### Documentation, Documentation, Documentation
|
||||
- Updated documentation for all public members of `PXSourceList` and its related classes and protocols.
|
||||
- Added documentation for new classes and `PXSourceListDelegate` methods.
|
||||
- Added documentation for `PXSourceList` delegate notifications.
|
||||
- Added a Documentation target to the Xcode project, which can be used to build documentation from source using [appledoc](http://gentlebytes.com/appledoc/).
|
||||
|
||||
### Other Changes
|
||||
- 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 ;)
|
||||
@@ -1,23 +0,0 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf250
|
||||
{\fonttbl\f0\fnil\fcharset0 Monaco;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
|
||||
|
||||
\f0\fs20 \cf0 (Note: Parts that are styled with a strikeout have been completed.)\strike \strikec0 \
|
||||
\
|
||||
1. Source List badge colours for Graphite theme set in system preferences\strike0\striked0 \
|
||||
\strike \strikec0 2. Implement custom drawing for drag and drop\
|
||||
\strike0\striked0 - Implemented by default by the Outline View\
|
||||
\strike \strikec0 3. Sort out way that Source List returns badge values \'96 use NSNumber?\strike0\striked0 \
|
||||
- No, return NSNotFound for -badgeValueForItem: instead if item doesn't have badge \
|
||||
4. Provide a bindings interface\
|
||||
5. Cross-group keyboard implementation?\
|
||||
6. Provide an isGroupItem: delegate method?\
|
||||
7. Change the way the Source List handles drag and drop to something more like iTunes/Finder?\
|
||||
8. Make GC-compatible\
|
||||
\
|
||||
Fix @nmarisi's bug:\
|
||||
- If you uncheck "Show Vertical Scroller" in IB for the NSScrollView that the Source List is contained in, the bounds of the Source List are extended so that the badges are cut off.\
|
||||
\
|
||||
\strike \strikec0 Fix @davedelong's Bug:\
|
||||
- Prevent images larger than that specified in the `iconSize` property being passed in to the sourceList:iconForItem: dataSource method.}
|
||||