PageRenderTime 79ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/letterbox/mooseyard/MYUtilities/MYAddressField.m

http://github.com/ccgus/letters
Objective C | 223 lines | 167 code | 46 blank | 10 comment | 24 complexity | 10ce9fb88ed5e01ebe4817036796c050 MD5 | raw file
  1. //
  2. // MYAddressField.m
  3. // YourMove
  4. //
  5. // Created by Jens Alfke on 7/16/08.
  6. // Copyright 2008 Jens Alfke. All rights reserved.
  7. //
  8. #import "MYAddressField.h"
  9. #import "RegexKitLite.h"
  10. #import <AddressBook/AddressBook.h>
  11. @interface MYAddressField ()
  12. @property (retain) MYAddressItem *selectedAddress;
  13. @end
  14. @implementation MYAddressField
  15. @synthesize defaultAddresses=_defaultAddresses, addressProperty=_property, selectedAddress=_selectedAddress;
  16. - (void) _computeAddresses
  17. {
  18. NSMutableArray *newAddresses = $marray();
  19. if( _property ) {
  20. if( _prefix.length ) {
  21. // Find all the people in the address book matching _prefix:
  22. ABAddressBook *ab = [ABAddressBook sharedAddressBook];
  23. ABSearchElement *search = [ABPerson searchElementForProperty: _property
  24. label: nil
  25. key: nil
  26. value: nil
  27. comparison: kABNotEqual];
  28. for( ABPerson *person in [ab recordsMatchingSearchElement: search] ) {
  29. ABMultiValue *values = [person valueForProperty: _property];
  30. NSString *first = [person valueForProperty: kABFirstNameProperty];
  31. NSString *last = [person valueForProperty: kABLastNameProperty];
  32. BOOL nameMatches = _prefix==nil || ([first.lowercaseString hasPrefix: _prefix]
  33. || [last.lowercaseString hasPrefix: _prefix]);
  34. for( int i=0; i<values.count; i++ ) {
  35. NSString *address = [values valueAtIndex: i];
  36. if( nameMatches || [address.lowercaseString hasPrefix: _prefix] ) {
  37. MYAddressItem *item = [[MYAddressItem alloc] initWithPerson: person
  38. addressType: _property
  39. address: address];
  40. [newAddresses addObject: item];
  41. [item release];
  42. }
  43. }
  44. }
  45. } else if( _defaultAddresses ) {
  46. [newAddresses addObjectsFromArray: _defaultAddresses];
  47. }
  48. }
  49. [newAddresses sortUsingSelector: @selector(compare:)];
  50. if( ifSetObj(&_addresses,newAddresses) )
  51. [self reloadData];
  52. }
  53. - (NSArray*) addresses
  54. {
  55. if( ! _addresses )
  56. [self _computeAddresses];
  57. return _addresses;
  58. }
  59. - (void) awakeFromNib
  60. {
  61. if( ! _addresses )
  62. _addresses = [[NSMutableArray alloc] init];
  63. _property = [kABEmailProperty retain];
  64. self.completes = NO;
  65. self.usesDataSource = YES;
  66. self.dataSource = self;
  67. self.delegate = self;
  68. }
  69. - (void) dealloc
  70. {
  71. [_addresses release];
  72. [_property release];
  73. [_prefix release];
  74. [_selectedAddress release];
  75. [super dealloc];
  76. }
  77. - (BOOL) isExpanded
  78. {
  79. id ax = NSAccessibilityUnignoredDescendant(self);
  80. return [[ax accessibilityAttributeValue: NSAccessibilityExpandedAttribute] boolValue];
  81. }
  82. - (void) setExpanded: (BOOL)expanded
  83. {
  84. id ax = NSAccessibilityUnignoredDescendant(self);
  85. [ax accessibilitySetValue: $object(expanded) forAttribute: NSAccessibilityExpandedAttribute];
  86. }
  87. - (void) controlTextDidChange: (NSNotification*)n
  88. {
  89. if( _prefix.length == 0 )
  90. self.expanded = YES;
  91. if( ifSetObj(&_prefix, self.stringValue.lowercaseString) )
  92. [self _computeAddresses];
  93. MYAddressItem *item = [[MYAddressItem alloc] initWithString: self.stringValue
  94. addressType: _property];
  95. self.selectedAddress = item;
  96. [item release];
  97. if( _prefix.length == 0 )
  98. self.expanded = NO;
  99. //Log(@"Address selection = %@",self.selectedAddress);
  100. }
  101. - (void)comboBoxSelectionDidChange:(NSNotification *)notification
  102. {
  103. int sel = self.indexOfSelectedItem;
  104. self.selectedAddress = sel>=0 ?[self.addresses objectAtIndex: sel] :nil;
  105. //Log(@"Address selection = %@",self.selectedAddress);
  106. }
  107. #pragma mark -
  108. #pragma mark DATA SOURCE:
  109. - (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox
  110. {
  111. return self.addresses.count;
  112. }
  113. - (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index
  114. {
  115. return [[self.addresses objectAtIndex: index] description];
  116. }
  117. @end
  118. @implementation MYAddressItem
  119. - (id) initWithName: (NSString*)name
  120. addressType: (NSString*)addressType address: (NSString*)address
  121. {
  122. self = [super init];
  123. if( self ) {
  124. _name = name.length ?[name copy] :nil;
  125. _addressType = [addressType copy];
  126. _address = [address copy];
  127. }
  128. return self;
  129. }
  130. - (id) initWithPerson: (ABPerson*)person
  131. addressType: (NSString*)addressType address: (NSString*)address
  132. {
  133. NSString *first = [person valueForProperty: kABFirstNameProperty] ?: @"";
  134. NSString *last = [person valueForProperty: kABLastNameProperty] ?: @"";
  135. NSString *name = $sprintf(@"%@ %@", first,last);
  136. self = [self initWithName: name addressType: addressType address: address];
  137. if( self )
  138. _uuid = person.uniqueId.copy;
  139. return self;
  140. }
  141. - (id) initWithString: (NSString*)str addressType: (NSString*)addressType
  142. {
  143. #define kJustAddrRegex "[-a-zA-Z0-9%_+.]+(?:@[-a-zA-Z0-9.]+)"
  144. static NSString* const kNameAndAddrRegex = @"^\\s*(\\S+)?\\s*<("kJustAddrRegex")>\\s*$";
  145. static NSString* const kAddrRegex = @"^\\s*("kJustAddrRegex")\\s*$";
  146. NSString *name = nil;
  147. NSString *address = [str stringByMatching: kNameAndAddrRegex capture: 2];
  148. if( address ) {
  149. name = [str stringByMatching: kNameAndAddrRegex capture: 1];
  150. } else {
  151. address = [str stringByMatching: kAddrRegex];
  152. }
  153. if( ! address ) {
  154. [self release];
  155. return nil;
  156. }
  157. return [self initWithName: name addressType: addressType address: address];
  158. }
  159. @synthesize name=_name, addressType=_addressType, address=_address;
  160. - (ABPerson*) person
  161. {
  162. if( _uuid )
  163. return (ABPerson*) [[ABAddressBook sharedAddressBook] recordForUniqueId: _uuid];
  164. else
  165. return nil;
  166. }
  167. - (NSString*) description
  168. {
  169. return $sprintf(@"%@%@<%@>", _name,(_name ?@" ":@""),_address);
  170. }
  171. - (NSComparisonResult) compare: (MYAddressItem*)other
  172. {
  173. NSString *str1 = _name ?:_address;
  174. NSString *str2 = other->_name ?: other->_address;
  175. return [str1 localizedCaseInsensitiveCompare: str2];
  176. }
  177. @end