1#
2#  PeopleDataSource.rb
3#  ABPresence
4#
5#  Created by Laurent Sansonetti on 1/4/07.
6#  Copyright (c) 2007 Apple Computer. All rights reserved.
7#
8
9class PeopleDataSource < NSObject
10  ib_outlet :table
11
12  # Initialize and register for AddressBook notifications
13  def awakeFromNib
14    @imPersonStatus = []
15    @abPeople = []
16
17    nCenter = NSNotificationCenter.defaultCenter
18    nCenter.objc_send :addObserver, self,
19                      :selector, 'abDatabaseChangedExternallyNotification:',
20                      :name, KABDatabaseChangedExternallyNotification,
21                      :object, nil
22    nCenter.objc_send :addObserver, self,
23                      :selector, 'addressBookPersonStatusChanged:',
24                      :name, KAddressBookPersonStatusChanged,
25                      :object, nil
26    
27    reloadABPeople
28  end
29
30  # Data Loading
31
32  def bestStatusForPerson(person)
33    bestStatus = IMPersonStatusOffline # Let's assume they're offline to start
34    IMService.allServices.to_a.each do |service|
35      service.screenNamesForPerson(person).to_a.each do |screenName|
36        dict = service.infoForScreenName(screenName)
37        next if dict.nil?
38        status = dict.objectForKey(IMPersonStatusKey)
39        next if status.nil?
40        thisStatus = status.intValue
41        if thisStatus > bestStatus
42          bestStatus = thisStatus 
43        end
44      end
45    end
46    return bestStatus
47  end
48
49  # This dumps all the status information and rebuilds the array against the current _abPeople
50  # Fairly expensive, so this is only done when necessary
51  def rebuildStatusInformation
52    @imPersonStatus = @abPeople.map { |person| bestStatusForPerson(person) }
53    @table.reloadData
54  end
55	
56
57  # Rebuild status information for a given person, much faster than a full rebuild
58  def rebuildStatusInformationForPerson(forPerson)
59    @abPeople.each_with_index do |person, i|
60      next unless person == forPerson
61      @imPersonStatus[i] = bestStatusForPerson(person)
62    end
63    @table.reloadData
64  end
65  
66  # This will do a full flush of people in our AB Cache, along with rebuilding their status 
67  def reloadABPeople
68    @abPeople = ABAddressBook.sharedAddressBook.people.to_a.sort do |x, y|
69      x.displayName.to_s <=> y.displayName.to_s
70    end
71    rebuildStatusInformation
72  end
73
74  # NSTableView Data Source
75  
76  def numberOfRowsInTableView(tableView)
77    @abPeople ? @abPeople.size : 0
78  end
79  
80  def tableView_objectValueForTableColumn_row(tableView, tableColumn, row)
81    case tableColumn.identifier.to_s
82      when 'image'
83        case @imPersonStatus[row]
84          when IMPersonStatusAvailable, IMPersonStatusIdle
85            NSImage.imageNamed('online')
86          when IMPersonStatusAway
87            NSImage.imageNamed('offline')
88        end
89      when 'name'
90        @abPeople[row].displayName
91    end
92  end
93
94  # Notifications
95
96  # Posted from ServiceWatcher
97  # The object of this notification is an ABPerson who's status has changed
98  def addressBookPersonStatusChanged(notification)
99    rebuildStatusInformationForPerson(notification.object)
100  end
101
102  # If the AB database changes, force a reload of everyone
103  # We could look in the notification to catch differential updates, but for now
104  # this is fine.
105  def abDatabaseChangedExternallyNotification(notification)
106    reloadABPeople
107  end
108
109end
110