// ADSinglePropertyView.m (this is -*- ObjC -*-) // // \author: Björn Giesler // // Address View Framework for GNUstep // // $Author: rmottola $ // $Locker: $ // $Revision: 1.1 $ // $Date: 2007/03/29 22:36:04 $ /* system includes */ /* (none) */ /* my includes */ #include "ADSinglePropertyView.h" // redefine _(@"...") so that it looks into our bundle, not the main bundle #undef _ #define _(x) [[NSBundle bundleForClass: [ADSinglePropertyView class]] \ localizedStringForKey: x \ value: x \ table: nil] @interface ADSinglePropertyView (Private) - (void) _buildArrays; - (void) _handleDatabaseChanged: (NSNotification*) note; - (void) _selectGroupInBrowser: (id) sender; - (void) _doubleOnBrowser: (id) sender; @end @implementation ADSinglePropertyView (Private) - (void) _buildArrays { ADPropertyType type; NSArray *people; ADPerson *p; NSEnumerator *e; [_names release]; [_values release]; [_namesUnthinned release]; [_people release]; _names = [[NSMutableArray alloc] init]; _namesUnthinned = [[NSMutableArray alloc] init]; _values = [[NSMutableArray alloc] init]; _people = [[NSMutableArray alloc] init]; type = [[ADPerson class] typeOfProperty: _property]; if(_selectedGroup) { NSString *uid = [_selectedGroup uniqueId]; [_selectedGroup autorelease]; _selectedGroup = [[_book recordForUniqueId: uid] retain]; } if(!_selectedGroup) people = [_book people]; else people = [_selectedGroup members]; people = [people sortedArrayUsingSelector: @selector(compareByScreenName:)]; e = [people objectEnumerator]; while((p = [e nextObject])) { if(type & ADMultiValueMask) { int i, index; BOOL hasPreferred; id val; val = [p valueForProperty: _property]; if(![val count]) continue; hasPreferred = NO; // does it have values matching the // preferred label? if(_prefLabel) for(i=0; i<[val count]; i++) if([_prefLabel isEqualToString: [val labelAtIndex: i]]) { hasPreferred = YES; break; } for(i=0,index=0; i<[val count]; i++) { if(hasPreferred && ![_prefLabel isEqualToString: [val labelAtIndex: i]]) continue; if(index==0) { NSString *name = [p screenName]; if(p == [_book me]) name = [name stringByAppendingString: _(@" (Me)")]; [_names addObject: name]; } else [_names addObject: @""]; [_namesUnthinned addObject: [p screenName]]; [_values addObject: [[val valueAtIndex: i] description]]; [_people addObject: p]; index++; } } else { if(![p valueForProperty: _property]) continue; [_names addObject: [p screenName]]; [_namesUnthinned addObject: [p screenName]]; [_values addObject: [[p valueForProperty: _property] description]]; } } [_peopleTable reloadData]; } - (void) _handleDatabaseChanged: (NSNotification*) note { int row; [self _buildArrays]; row = [_groupsBrowser selectedRowInColumn: 0]; [_groupsBrowser reloadColumn: 0]; [_groupsBrowser selectRow: row inColumn: 0]; } - (void) _handleDoubleclickOnTable: (id) sender { NSString *name; NSString *value; int row; row = [sender selectedRow]; if(row == -1 || !_delegate) return; name = [_namesUnthinned objectAtIndex: row]; value = [_values objectAtIndex: row]; if([_delegate respondsToSelector: @selector(doubleClickOnName:value:inView:)]) [_delegate doubleClickOnName: name value: value inView: self]; } - (void) _selectGroupInBrowser: (id) sender { int row; ADGroup *newGroup = nil; if(!_book) _book = [ADAddressBook sharedAddressBook]; row = [sender selectedRowInColumn: 0]; if(row) newGroup = [[_book groups] objectAtIndex: row-1]; if(newGroup == _selectedGroup) return; [_selectedGroup release]; _selectedGroup = [newGroup retain]; [_peopleTable deselectAll: self]; [self _buildArrays]; [_peopleTable reloadData]; } - (void) _doubleOnBrowser: (id) sender { [self autoselectAccordingToMode: _autosel]; } @end @implementation ADSinglePropertyView - initWithFrame: (NSRect) frame { NSRect r; if(![super initWithFrame: frame]) return nil; [self setDisplayedProperty: ADEmailProperty]; _selectedGroup = nil; [self setAutoresizesSubviews: YES]; r = frame; r.origin = NSMakePoint(0, 0); _splitView = [[[NSSplitView alloc] initWithFrame: r] autorelease]; [_splitView setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; [_splitView setVertical: YES]; [_splitView setDelegate: self]; [self addSubview: _splitView]; r = frame; r.origin = NSMakePoint(0, 0); r.size.width = frame.size.width/4; _groupsBrowser = [[[NSBrowser alloc] initWithFrame: r] autorelease]; [_groupsBrowser setMaxVisibleColumns: 1]; [_groupsBrowser setAllowsEmptySelection: NO]; [_groupsBrowser setAllowsMultipleSelection: NO]; [_groupsBrowser setDelegate: self]; [_groupsBrowser setTarget: self]; [_groupsBrowser setAction: @selector(_selectGroupInBrowser:)]; [_groupsBrowser setDoubleAction: @selector(_doubleOnBrowser:)]; [_groupsBrowser loadColumnZero]; [_groupsBrowser selectRow: 0 inColumn: 0]; [_splitView addSubview: _groupsBrowser]; r = frame; r.origin = NSMakePoint(0, 0); r.size.width = (frame.size.width*3)/4; _ptScrollView = [[[NSScrollView alloc] initWithFrame: r] autorelease]; [_ptScrollView setRulersVisible: YES]; [_ptScrollView setHasVerticalScroller: YES]; [_ptScrollView setHasHorizontalScroller: YES]; [_ptScrollView setBorderType: NSBezelBorder]; [_ptScrollView setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; [_splitView addSubview: _ptScrollView]; _peopleTable = [[[NSTableView alloc] initWithFrame: frame] autorelease]; [_peopleTable setDataSource: self]; [_peopleTable setTarget: self]; [_peopleTable setDelegate: self]; [_peopleTable setDoubleAction: @selector(_handleDoubleclickOnTable:)]; _nameColumn = [[[NSTableColumn alloc] initWithIdentifier: @"Name"] autorelease]; [[_nameColumn headerCell] setStringValue: _(@"Person Name")]; _propertyColumn = [[[NSTableColumn alloc] initWithIdentifier: @"Property"] autorelease]; [[_propertyColumn headerCell] setStringValue: ADLocalizedPropertyOrLabel(_property)]; [_peopleTable addTableColumn: _nameColumn]; [_peopleTable addTableColumn: _propertyColumn]; [_peopleTable setAutoresizesAllColumnsToFit: YES]; [_peopleTable setAllowsMultipleSelection: YES]; [_peopleTable sizeToFit]; [_ptScrollView setDocumentView: _peopleTable]; _delegate = nil; _prefLabel = nil; _autosel = ADAutoselectFirstValue; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_handleDatabaseChanged:) name: ADDatabaseChangedExternallyNotification object: nil]; return self; } - (void) setDelegate: (id) delegate { _delegate = delegate; } - (id) delegate { return _delegate; } - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver: self]; } - (void) setDisplayedProperty: (NSString*) property { ADPropertyType type; if([_property isEqualToString: property]) return; if(!_book) _book = [ADAddressBook sharedAddressBook]; type = [[ADPerson class] typeOfProperty: property]; if(type == ADErrorInProperty) { NSLog(@"Trying to set unknown property %@\n", property); return; } [_property release]; _property = [property copy]; [self _buildArrays]; [[_propertyColumn headerCell] setStringValue: ADLocalizedPropertyOrLabel(_property)]; [[_peopleTable headerView] setNeedsDisplay: YES]; [_peopleTable deselectAll: self]; [_peopleTable reloadData]; } - (NSString*) displayedProperty { return _property; } - (void) setPreferredLabel: (NSString*) preferredLabel { if([preferredLabel isEqualToString: _prefLabel]) return; [_prefLabel release]; _prefLabel = [preferredLabel copy]; [self _buildArrays]; if(_selectedGroup) [self autoselectAccordingToMode: _autosel]; } - (NSString*) preferredLabel { return _prefLabel; } - (void) setAutoselectMode: (ADAutoselectMode) mode { _autosel = mode; } - (ADAutoselectMode) autoselectMode { return _autosel; } - (void) autoselectAccordingToMode: (ADAutoselectMode) mode { int i; ADPerson *p; [_peopleTable reloadData]; switch(mode) { case ADAutoselectAll: [_peopleTable selectAll: self]; return; case ADAutoselectFirstValue: [_peopleTable deselectAll: self]; for(i=0; i<[_people count]; i++) { if(p == [_people objectAtIndex: i]) continue; p = [_people objectAtIndex: i]; [_peopleTable selectRow: i byExtendingSelection: YES]; } return; default: return; } } - (NSArray*) selectedNamesAndValues { NSMutableArray *retval; NSEnumerator *e; NSNumber *r; retval = [NSMutableArray array]; e = [_peopleTable selectedRowEnumerator]; while((r = [e nextObject])) { int i = [r intValue]; [retval addObject: [NSArray arrayWithObjects: [_namesUnthinned objectAtIndex: i], [_values objectAtIndex: i], nil]]; } return [NSArray arrayWithArray: retval]; } - (NSArray*) selectedPeopleAndValues { NSMutableArray *retval; NSEnumerator *e; NSNumber *r; retval = [NSMutableArray array]; e = [_peopleTable selectedRowEnumerator]; while((r = [e nextObject])) { int i = [r intValue]; [retval addObject: [NSArray arrayWithObjects: [_people objectAtIndex: i], [_values objectAtIndex: i], [NSNumber numberWithInt: i], nil]]; } return [NSArray arrayWithArray: retval]; } - (NSArray*) selectedValues { NSMutableArray *retval; NSEnumerator *e; NSNumber *r; retval = [NSMutableArray array]; e = [_peopleTable selectedRowEnumerator]; while((r = [e nextObject])) [retval addObject: [_values objectAtIndex: [r intValue]]]; return [NSArray arrayWithArray: retval]; } - (ADGroup*) selectedGroup { return _selectedGroup; } - (NSArray*) selectedPeople { NSMutableArray *retval; NSEnumerator *e; NSNumber *r; retval = [NSMutableArray array]; e = [_peopleTable selectedRowEnumerator]; while((r = [e nextObject])) if(![retval containsObject: [_people objectAtIndex: [r intValue]]]) [retval addObject: [_people objectAtIndex: [r intValue]]]; return [NSArray arrayWithArray: retval]; } /* * NSTableDataSource methods */ - (int) numberOfRowsInTableView: (NSTableView*) view { return [_values count]; } - (id) tableView: (NSTableView*) v objectValueForTableColumn: (NSTableColumn*) col row: (int) row { NSString *val; if(col == _nameColumn) val = [_names objectAtIndex: row]; else val = [_values objectAtIndex: row]; return val; } - (BOOL) tableView: (NSTableView*) v shouldEditTableColumn: (NSTableColumn*) col row: (int) row { return NO; } /* * NSSplitView delegate methods */ - (float) splitView: (NSSplitView*) sender constrainMinCoordinate: (float) proposedMin ofSubviewAt: (int) offset { if(offset == 0 && proposedMin < [_groupsBrowser minColumnWidth]) return [_groupsBrowser minColumnWidth]; return proposedMin; } - (float) splitView: (NSSplitView*) sender constrainMaxCoordinate: (float) proposedMax ofSubviewAt: (int) offset { NSRect r; r = [self frame]; if(offset == 0 && proposedMax > r.size.width - [_groupsBrowser minColumnWidth]) return r.size.width - [_groupsBrowser minColumnWidth]; return proposedMax; } /* * NSBrowser delegate methods */ - (int) browser: (NSBrowser*) b numberOfRowsInColumn: (int) col { if(!_book) _book = [ADAddressBook sharedAddressBook]; return [[_book groups] count]+1; } - (NSString*) browser: (NSBrowser*) b titleOfColumn: (int) col { return _(@"Groups"); } - (void) browser: (NSBrowser*) b willDisplayCell: (NSBrowserCell*) cell atRow: (int) row column: (int) col { if(!_book) _book = [ADAddressBook sharedAddressBook]; if(row) [cell setStringValue: [[[_book groups] objectAtIndex: row-1] valueForProperty: ADGroupNameProperty]]; else [cell setStringValue: _(@"All")]; [cell setLeaf: YES]; } @end