# HG changeset patch # User Jens Alfke # Date 1216326574 25200 # Node ID d6ab9f52b4d77ab280861ecf0eb2dbf1795cd743 # Parent a1044ae95953a31396593e6d8aa1d0c7600797ad Initial checkin of MYAddressField, a combo-box for entering email or IM addresses. diff -r a1044ae95953 -r d6ab9f52b4d7 MYAddressField.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MYAddressField.h Thu Jul 17 13:29:34 2008 -0700 @@ -0,0 +1,43 @@ +// +// MYAddressField.h +// YourMove +// +// Created by Jens Alfke on 7/16/08. +// Copyright 2008 Jens Alfke. All rights reserved. +// + +#import +@class MYAddressItem, ABPerson; + + +@interface MYAddressField : NSComboBox +{ + NSString *_property, *_prefix; + NSMutableArray *_addresses; + NSArray *_defaultAddresses; + MYAddressItem *_selectedAddress; +} + +@property (getter=isExpanded) BOOL expanded; + +@property (copy) NSString *addressProperty; +@property (copy) NSArray *defaultAddresses; + +@property (readonly,retain) MYAddressItem* selectedAddress; + +@end + + + +@interface MYAddressItem : NSObject +{ + NSString *_name, *_addressType, *_address, *_uuid; +} +- (id) initWithName: (NSString*)name + addressType: (NSString*)addressType address: (NSString*)address; +- (id) initWithPerson: (ABPerson*)person + addressType: (NSString*)addressType address: (NSString*)address; +- (id) initWithString: (NSString*)str addressType: (NSString*)addressType; +@property (readonly) NSString *name, *addressType, *address; +@property (readonly) ABPerson *person; +@end \ No newline at end of file diff -r a1044ae95953 -r d6ab9f52b4d7 MYAddressField.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MYAddressField.m Thu Jul 17 13:29:34 2008 -0700 @@ -0,0 +1,223 @@ +// +// MYAddressField.m +// YourMove +// +// Created by Jens Alfke on 7/16/08. +// Copyright 2008 Jens Alfke. All rights reserved. +// + +#import "MYAddressField.h" +#import "RegexKitLite.h" +#import + + +@interface MYAddressField () +@property (retain) MYAddressItem *selectedAddress; +@end + + +@implementation MYAddressField + + +@synthesize defaultAddresses=_defaultAddresses, addressProperty=_property, selectedAddress=_selectedAddress; + + +- (void) _computeAddresses +{ + NSMutableArray *newAddresses = $marray(); + if( _property ) { + if( _prefix.length ) { + // Find all the people in the address book matching _prefix: + ABAddressBook *ab = [ABAddressBook sharedAddressBook]; + ABSearchElement *search = [ABPerson searchElementForProperty: _property + label: nil + key: nil + value: nil + comparison: kABNotEqual]; + for( ABPerson *person in [ab recordsMatchingSearchElement: search] ) { + ABMultiValue *values = [person valueForProperty: _property]; + NSString *first = [person valueForProperty: kABFirstNameProperty]; + NSString *last = [person valueForProperty: kABLastNameProperty]; + BOOL nameMatches = _prefix==nil || ([first.lowercaseString hasPrefix: _prefix] + || [last.lowercaseString hasPrefix: _prefix]); + for( int i=0; i=0 ?[self.addresses objectAtIndex: sel] :nil; + //Log(@"Address selection = %@",self.selectedAddress); +} + + +#pragma mark - +#pragma mark DATA SOURCE: + + +- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox +{ + return self.addresses.count; +} + +- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index +{ + return [[self.addresses objectAtIndex: index] description]; +} + + +@end + + + + +@implementation MYAddressItem + +- (id) initWithName: (NSString*)name + addressType: (NSString*)addressType address: (NSString*)address +{ + self = [super init]; + if( self ) { + _name = name.length ?[name copy] :nil; + _addressType = [addressType copy]; + _address = [address copy]; + } + return self; +} + +- (id) initWithPerson: (ABPerson*)person + addressType: (NSString*)addressType address: (NSString*)address +{ + NSString *first = [person valueForProperty: kABFirstNameProperty] ?: @""; + NSString *last = [person valueForProperty: kABLastNameProperty] ?: @""; + NSString *name = $sprintf(@"%@ %@", first,last); + + self = [self initWithName: name addressType: addressType address: address]; + if( self ) + _uuid = person.uniqueId.copy; + return self; +} + +- (id) initWithString: (NSString*)str addressType: (NSString*)addressType +{ + #define kJustAddrRegex "[-a-zA-Z0-9%_+.]+(?:@[-a-zA-Z0-9.]+)" + static NSString* const kNameAndAddrRegex = @"^\\s*(\\S+)?\\s*<("kJustAddrRegex")>\\s*$"; + static NSString* const kAddrRegex = @"^\\s*("kJustAddrRegex")\\s*$"; + + NSString *name = nil; + NSString *address = [str stringByMatching: kNameAndAddrRegex capture: 2]; + if( address ) { + name = [str stringByMatching: kNameAndAddrRegex capture: 1]; + } else { + address = [str stringByMatching: kAddrRegex]; + } + if( ! address ) { + [self release]; + return nil; + } + return [self initWithName: name addressType: addressType address: address]; +} + +@synthesize name=_name, addressType=_addressType, address=_address; + +- (ABPerson*) person +{ + if( _uuid ) + return (ABPerson*) [[ABAddressBook sharedAddressBook] recordForUniqueId: _uuid]; + else + return nil; +} + +- (NSString*) description +{ + return $sprintf(@"%@%@<%@>", _name,(_name ?@" ":@""),_address); +} + +- (NSComparisonResult) compare: (MYAddressItem*)other +{ + NSString *str1 = _name ?:_address; + NSString *str2 = other->_name ?: other->_address; + return [str1 localizedCaseInsensitiveCompare: str2]; +} + +@end