2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "AIContactController.h"
18 #import "AIContactInfoWindowController.h"
19 #import "ESContactInfoListController.h"
20 #import <Adium/AIListGroup.h>
21 #import <Adium/AIListObject.h>
22 #import <Adium/AIListOutlineView.h>
23 #import <Adium/AIMetaContact.h>
25 @implementation ESContactInfoListController
27 //The superclass's implementation does not expand metaContacts
28 - (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
32 if([contactList isKindOfClass:[AIMetaContact class]]){
33 return((index >= 0 && index < [(AIMetaContact *)contactList uniqueContainedObjectsCount]) ?
34 [(AIMetaContact *)contactList uniqueObjectAtIndex:index] :
37 return((index >= 0 && index < [(AIListGroup *)contactList containedObjectsCount]) ? [contactList objectAtIndex:index] : nil);
43 if ([item isKindOfClass:[AIMetaContact class]]){
44 return((index >= 0 && index < [(AIMetaContact *)item uniqueContainedObjectsCount]) ?
45 [(AIMetaContact *)item uniqueObjectAtIndex:index] :
48 return((index >= 0 && index < [(AIListGroup *)item containedObjectsCount]) ? [item objectAtIndex:index] : nil);
53 //The superclass's implementation does not expand metaContacts
54 - (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
58 if ([contactList isKindOfClass:[AIMetaContact class]]){
59 return([(AIMetaContact *)contactList uniqueContainedObjectsCount]);
61 return([(AIListGroup *)contactList containedObjectsCount]);
67 if([item isKindOfClass:[AIMetaContact class]]){
68 return([(AIMetaContact *)item uniqueContainedObjectsCount]);
70 return([(AIListGroup *)item containedObjectsCount]);
75 //The superclass's implementation does not expand metaContacts
76 - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
78 if([item isKindOfClass:[AIMetaContact class]] || [item isKindOfClass:[AIListGroup class]]){
86 * @brief Change the info window as the selection changes
88 * We want to configure for contact-specific information when a contact is selected in the drawer
89 * If no row is selected, we configure for the contactList root (the metaContact itself)
91 - (void)outlineViewSelectionDidChange:(NSNotification *)aNotification
93 if (!aNotification || [aNotification object] == contactListView){
94 int selectedRow = [contactListView selectedRow];
95 [(AIContactInfoWindowController *)delegate configureForListObject:((selectedRow != -1) ?
96 [contactListView itemAtRow:selectedRow] :
102 * @brief Remove the selected rows from the metaContact
104 - (void)outlineViewDeleteSelectedRows:(NSOutlineView *)outlineView
106 [(AIContactInfoWindowController *)delegate removeContact:outlineView];
110 * @brief Validate a drag and drop operation
112 - (NSDragOperation)outlineView:(NSOutlineView*)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
114 NSPasteboard *draggingPasteboard = [info draggingPasteboard];
115 NSString *avaliableType = [draggingPasteboard availableTypeFromArray:[NSArray arrayWithObject:@"AIListObject"]];
117 //No dropping into contacts
118 if([avaliableType isEqualToString:@"AIListObject"]){
120 id primaryDragItem = nil;
122 //If we don't have drag items, we are dragging from another instance; build our own dragItems array
123 //using the supplied internalObjectIDs
125 if ([[draggingPasteboard availableTypeFromArray:[NSArray arrayWithObject:@"AIListObjectUniqueIDs"]] isEqualToString:@"AIListObjectUniqueIDs"]){
126 NSArray *dragItemsUniqueIDs;
127 NSMutableArray *arrayOfDragItems;
129 NSEnumerator *enumerator;
131 dragItemsUniqueIDs = [draggingPasteboard propertyListForType:@"AIListObjectUniqueIDs"];
132 arrayOfDragItems = [NSMutableArray array];
134 enumerator = [dragItemsUniqueIDs objectEnumerator];
135 while (uniqueID = [enumerator nextObject]){
136 [arrayOfDragItems addObject:[[adium contactController] existingListObjectWithUniqueID:uniqueID]];
139 //We will release this when the drag is completed
140 dragItems = [arrayOfDragItems retain];
144 primaryDragItem = [dragItems objectAtIndex:0];
146 if([primaryDragItem isKindOfClass:[AIListGroup class]]){
147 //Disallow dragging groups into the contact info window
148 return(NSDragOperationNone);
151 //Disallow dragging contacts into anything besides the contact list
152 if(index == NSOutlineViewDropOnItemIndex){
154 //The contactList is 'nil' to the outlineView
155 [outlineView setDropItem:nil dropChildIndex:[outlineView rowForItem:item]];
160 return(NSDragOperationPrivate);
164 - (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
166 NSPasteboard *draggingPasteboard = [info draggingPasteboard];
167 NSString *availableType = [draggingPasteboard availableTypeFromArray:[NSArray arrayWithObject:@"AIListObject"]];
169 //No longer in a drag, so allow tooltips again
170 if([availableType isEqualToString:@"AIListObject"]){
172 //If we don't have drag items, we are dragging from another instance; build our own dragItems array
173 //using the supplied internalObjectIDs
175 if ([[draggingPasteboard availableTypeFromArray:[NSArray arrayWithObject:@"AIListObjectUniqueIDs"]] isEqualToString:@"AIListObjectUniqueIDs"]){
176 NSArray *dragItemsUniqueIDs;
177 NSMutableArray *arrayOfDragItems;
179 NSEnumerator *enumerator;
181 dragItemsUniqueIDs = [draggingPasteboard propertyListForType:@"AIListObjectUniqueIDs"];
182 arrayOfDragItems = [NSMutableArray array];
184 enumerator = [dragItemsUniqueIDs objectEnumerator];
185 while (uniqueID = [enumerator nextObject]){
186 [arrayOfDragItems addObject:[[adium contactController] existingListObjectWithUniqueID:uniqueID]];
189 //We will release this when the drag is completed
190 dragItems = [arrayOfDragItems retain];
194 //The tree root is not associated with our root contact list group, so we need to make that association here
195 if(item == nil) item = contactList;
197 //Move the list object to its new location
198 if([item isKindOfClass:[AIMetaContact class]]){
200 NSMutableArray *realDragItems = [NSMutableArray array];
201 NSEnumerator *enumerator;
202 AIListObject *aDragItem;
204 if (index == [outlineView numberOfRows]){
205 index = [item containedObjectsCount];
207 //The outline view has one unique contact for each service/UID combination, while the metacontact
208 //has a containedObjectsArray with multiple contacts for each. We want to find which item is at
209 //our drop row, then determine the index in the metacontact of that item. That's the index we move to.
210 index = [(AIMetaContact *)item indexOfObject:[outlineView itemAtRow:index]];
213 enumerator = [dragItems objectEnumerator];
214 while (aDragItem = [enumerator nextObject]){
215 if ([aDragItem isMemberOfClass:[AIListContact class]]){
216 //For listContacts, add all contacts with the same service and UID (on all accounts)
217 [realDragItems addObjectsFromArray:[[adium contactController] allContactsWithService:[aDragItem service]
218 UID:[aDragItem UID]]];
220 [realDragItems addObject:aDragItem];
224 [[adium contactController] moveListObjects:realDragItems toGroup:item index:index];
225 [outlineView reloadData];
229 //Call super and return its value
230 return([super outlineView:outlineView acceptDrop:info item:item childIndex:index]);
233 //Due to a bug in NSDrawer, convertPoint:fromView reports a point too low by the trailingOffset
234 //when our contact list is in a drawer.
235 - (AIListObject *)contactListItemAtScreenPoint:(NSPoint)screenPoint
237 NSPoint viewPoint = [contactListView convertPoint:[[contactListView window] convertScreenToBase:screenPoint] fromView:[[contactListView window] contentView]];
239 viewPoint.y += [(AIContactInfoWindowController *)delegate drawerTrailingOffset];
241 AIListObject *hoveredObject = [contactListView itemAtRow:[contactListView rowAtPoint:viewPoint]];
243 return(hoveredObject);
246 //We want to just show UIDs whereever possible
247 - (BOOL)useAliasesInContactListAsRequested
252 //We don't want to change text colors based on the user's status or state
253 - (BOOL)shouldUseContactTextColors{