adium/adium

Docs: Minor tweaks.
adium-1.5.11
2016-09-04, Robert Vehse
307f53385811
Docs: Minor tweaks.
/*
* Adium is the legal property of its developers, whose names are listed in the copyright file included
* with this source distribution.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "OWABSearchWindowController.h"
#import <Adium/AIAccountControllerProtocol.h>
#import <Adium/AIService.h>
#import <Adium/AIServiceMenu.h>
#import <Adium/AIServiceIcons.h>
#import "AIAddressBookController.h"
#import <AIUtilities/AIMenuAdditions.h>
#import <AIUtilities/AIPopUpButtonAdditions.h>
#import <AIUtilities/AIImageViewWithImagePicker.h>
#import <AddressBook/AddressBook.h>
#import <AddressBook/ABPeoplePickerView.h>
#import <AddressBook/ABPerson.h>
#define AB_SEARCH_NIB @"ABSearch"
@interface NSObject (OWABSearchWindowControllerDelegate_Weak)
- (void)OWABSearchWindowControllerDidSelectPerson:(OWABSearchWindowController *)controller;
@end
@interface OWABSearchWindowController ()
- (id)initWithWindowNibName:(NSString *)windowNibName initialService:(AIService *)inService;
- (void)_configurePeoplePicker;
- (void)_setCarryingWindow:(NSWindow *)inWindow;
- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
- (void)buildContactTypeMenu;
- (void)ensureValidContactTypeSelection;
- (void)configureForCurrentServiceType;
- (IBAction)selectServiceType:(id)sender;
- (void)_setService:(AIService *)inService;
- (void)_setPerson:(ABPerson *)inPerson;
- (void)_setScreenName:(NSString *)inName;
@end
/*!
* @class OWABSearchWindowController
* @brief Window controller for searching people in the Address Book database.
*/
@implementation OWABSearchWindowController
static ABAddressBook *sharedAddressBook = nil;
/*!
* @brief Prompt for searching a person within the AB database.
*
* @param parentWindow Window on which to show the prompt as a sheet. Pass nil for a panel prompt.
* @param inService The AIService to display initially
*/
+ (id)promptForNewPersonSearchOnWindow:(NSWindow *)parentWindow initialService:(AIService *)inService
{
OWABSearchWindowController *newABSearchWindow;
newABSearchWindow = [[self alloc] initWithWindowNibName:AB_SEARCH_NIB initialService:inService];
if (parentWindow) {
[NSApp beginSheet:[newABSearchWindow window]
modalForWindow:parentWindow
modalDelegate:newABSearchWindow
didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo:nil];
[newABSearchWindow _setCarryingWindow:parentWindow];
} else {
[newABSearchWindow showWindow:nil];
}
return [newABSearchWindow autorelease];
}
/*!
* @brief Initialize
*/
- (id)initWithWindowNibName:(NSString *)windowNibName initialService:(AIService *)inService
{
self = [super initWithWindowNibName:windowNibName];
if (self) {
delegate = nil;
person = nil;
screenName = nil;
carryingWindow = nil;
contactImage = nil;
service = [inService retain];
if (!sharedAddressBook)
sharedAddressBook = [[ABAddressBook sharedAddressBook] retain];
}
return self;
}
/*!
* @brief Deallocate
*/
- (void)dealloc
{
[self setDelegate:nil];
[person release];
[screenName release];
[service release];
[carryingWindow release];
[contactImage release];
[sharedAddressBook release]; sharedAddressBook = nil;
[super dealloc];
}
/*!
* @brief Setup the window before it is displayed
*/
- (void)windowDidLoad
{
[[self window] center];
//Localized strings
//Search window
[[self window] setTitle:AILocalizedString(@"Search In Address Book", nil)];
[selectButton setLocalizedString:AILocalizedString(@"Select Buddy", nil)];
[cancelButton setLocalizedString:AILocalizedString(@"Cancel", nil)];
[newPersonButton setLocalizedString:AILocalizedString(@"New Person", nil)];
//New contact window
[newContactPanel setTitle:AILocalizedString(@"Create New Person", nil)];
[label_mainTitle setLocalizedString:AILocalizedString(@"Enter the contact's type and screen name/number:", nil)];
[label_contactType setLocalizedString:AILocalizedString(@"Contact Type:", "Contact type service dropdown label in Add Contact")];
[label_secondaryTitle setLocalizedString:AILocalizedString(@"Address Book Information (optional):", nil)];
[label_firstName setLocalizedString:AILocalizedString(@"First Name:", nil)];
[label_lastName setLocalizedString:AILocalizedString(@"Last Name:", nil)];
[label_nickname setLocalizedString:AILocalizedString(@"Nickname:", nil)];
[label_email setLocalizedString:AILocalizedString(@"Email:", nil)];
[label_contactIcon setLocalizedString:AILocalizedString(@"Contact Icon", "Contact icon label in create new AB person")];
[addContactButton setLocalizedString:AILocalizedString(@"Add Contact", nil)];
[addContactCancelButton setLocalizedString:AILocalizedString(@"Cancel", nil)];
[imageView_contactIcon setMaxSize:NSMakeSize(256, 256)];
[self _configurePeoplePicker];
[[self window] selectKeyViewFollowingView:peoplePicker];
}
/*!
* @brief Setup our ABPeoplePickerView
*/
- (void)_configurePeoplePicker
{
NSTextField *accessoryView = [[[NSTextField alloc] init] autorelease];
NSString *property;
//Create a small explanation text
[accessoryView setStringValue:AILocalizedString(@"Select an entry from your address book, or add a new person.",
nil)];
[accessoryView setFont:[NSFont systemFontOfSize:10.0f]];
[accessoryView setDrawsBackground:NO];
[accessoryView setEnabled:NO];
[accessoryView setBezeled:NO];
[accessoryView sizeToFit];
//And attach it to our people picker view
[peoplePicker setAccessoryView:accessoryView];
//Configure our people picker
[peoplePicker setAllowsGroupSelection:NO];
[peoplePicker setAllowsMultipleSelection:NO];
[peoplePicker setValueSelectionBehavior:ABSingleValueSelection];
[peoplePicker setTarget:self];
[peoplePicker setNameDoubleAction:@selector(select:)];
//We show only the active services
for (AIService *aService in [adium.accountController activeServicesIncludingCompatibleServices:YES]) {
property = [AIAddressBookController propertyFromService:aService];
if (property && ![[peoplePicker properties] containsObject:property])
[peoplePicker addProperty:property];
}
//Display our initial service if we were passed one
if (service) {
property = [AIAddressBookController propertyFromService:service];
if (property && [[peoplePicker properties] containsObject:property]) {
[peoplePicker setDisplayedProperty:property];
}
}
}
/*!
* @brief Hide ourself and inform our delegate
*/
- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
if (delegate && returnCode == NSOKButton)
[delegate absearchWindowControllerDidSelectPerson:self];
[sheet orderOut:nil];
}
/*!
* @brief Cancel
*/
- (IBAction)cancel:(id)sender
{
if ([self windowShouldClose:nil]) {
if ([[self window] isSheet]) {
[NSApp endSheet:[self window] returnCode:NSCancelButton];
} else {
[[self window] close];
}
}
}
/*!
* @brief Select a person
*/
- (IBAction)select:(id)sender
{
NSArray *selectedValues = [peoplePicker selectedValues];
//Set the selected screen name
if ([selectedValues count] > 0)
[self _setScreenName:[selectedValues objectAtIndex:0]];
//Set the selected service
[self _setService:[AIAddressBookController serviceFromProperty:[peoplePicker displayedProperty]]];
//Set the selected person
[self _setPerson:[[peoplePicker selectedRecords] objectAtIndex:0]];
//Close our window
if ([self windowShouldClose:nil]) {
if ([[self window] isSheet]) {
[NSApp endSheet:[self window] returnCode:NSOKButton];
} else {
[[self window] close];
if (delegate)
[delegate absearchWindowControllerDidSelectPerson:self];
}
}
}
/*!
* @brief Close the people search sheet, and display the create new person sheet
*/
- (IBAction)createNewPerson:(id)sender
{
//Close the first sheet
[self cancel:nil];
//Setup our new window,
[self setWindow:newContactPanel];
[newContactPanel setDelegate:self];
//and show it
if (carryingWindow) {
[NSApp beginSheet:newContactPanel
modalForWindow:carryingWindow
modalDelegate:self
didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo:nil];
} else {
[self showWindow:nil];
[[self window] center];
}
//Configure the views of our new window
[self buildContactTypeMenu];
[self configureForCurrentServiceType];
}
/*!
* @brief Create a new person and add it to the address book database
*/
- (IBAction)addPerson:(id)sender
{
ABPerson *newPerson = [[[ABPerson alloc] init] autorelease];
NSString *contactID = [[textField_contactID stringValue] stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//Create the new contact
if (![contactID isEqualToString:@""]) {
ABMutableMultiValue *value = [[ABMutableMultiValue alloc] init];
NSString *identifier = nil;
NSString *serviceIndentifier = [AIAddressBookController propertyFromService:service];
identifier = [value addValue:contactID withLabel:serviceIndentifier];
if (identifier) {
NSString *email = [[textField_email stringValue] stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//Set the person's IM id
[newPerson setValue:value
forProperty:serviceIndentifier];
//Clean our multi value
[value removeValueAndLabelAtIndex:[value indexForIdentifier:identifier]];
//Set the person's email address
if (![email isEqualToString:@""]) {
identifier = [value addValue:[textField_email stringValue] withLabel:kABEmailProperty];
if (identifier) {
[newPerson setValue:value
forProperty:kABEmailProperty];
}
}
//Set the person's first name
[newPerson setValue:[textField_firstName stringValue]
forProperty:kABFirstNameProperty];
//Set the person's last name
[newPerson setValue:[textField_lastName stringValue]
forProperty:kABLastNameProperty];
//Set the person's nickname
[newPerson setValue:[textField_nickname stringValue]
forProperty:kABNicknameProperty];
//Set the person's image
if (contactImage)
[newPerson setImageData:contactImage];
//Add our newly created person to the AB database
if ([sharedAddressBook addRecord:newPerson] && [sharedAddressBook save]) {
[self _setPerson:newPerson];
[self _setScreenName:contactID];
//Close our window
if ([self windowShouldClose:nil]) {
if ([[self window] isSheet]) {
[NSApp endSheet:[self window] returnCode:NSOKButton];
} else {
[[self window] close];
if (delegate)
[delegate absearchWindowControllerDidSelectPerson:self];
}
}
} else {
//Cancel if we can't add our person to the AB database.
[self cancel:nil];
}
}
//Clean up
[value release];
} else {
//We didn't get a contact id.
//This is equal to pressing the cancel button.
[self cancel:nil];
}
}
/*!
* @brief Set our delegat
*/
- (void)setDelegate:(id)newDelegate
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
if (delegate) {
[nc removeObserver:delegate
name:OWABSearchWindowControllerDidSelectPersonNotification
object:self];
}
if (newDelegate) {
[nc addObserver:newDelegate
selector:@selector(OWABSearchWindowControllerDidSelectPerson:)
name:OWABSearchWindowControllerDidSelectPersonNotification
object:self];
}
[delegate release];
delegate = [newDelegate retain];
}
/*!
* @brief Returns our delegate
*/
- (id)delegate
{
return delegate;
}
#pragma mark -
/*!
* @brief Returns the selected person.
*/
- (ABPerson *)selectedPerson
{
return person;
}
/*!
* @brief Returns the selected person's screen name/number.
*/
- (NSString *)selectedScreenName
{
return screenName;
}
/*!
* @brief Returns the selected person's name like it's displayed in AB.
*/
- (NSString *)selectedName
{
NSString *result = nil;
NSString *firstName = [person valueForProperty:kABFirstNameProperty];
NSString *lastName = [person valueForProperty:kABLastNameProperty];
//Make sure we don't get "(null)" in our result
if (firstName && lastName) {
if ([sharedAddressBook defaultNameOrdering] == kABFirstNameFirst)
result = [firstName stringByAppendingFormat:@" %@", lastName];
else
result = [lastName stringByAppendingFormat:@" %@", firstName];
}
else if (firstName)
result = firstName;
else if (lastName)
result = lastName;
return result;
}
/*!
* @brief Returns the selected person's nickname.
*/
- (NSString *)selectedAlias
{
return [person valueForProperty:kABNicknameProperty];
}
/*!
* @brief Returns the service of the selected screen name/number.
*/
- (AIService *)selectedService
{
return service;
}
#pragma mark -
#pragma mark Private
/*!
* @brief Build and configure the menu of contact service types
*/
- (void)buildContactTypeMenu
{
//Rebuild the menu
[popUp_contactType setMenu:[AIServiceMenu menuOfServicesWithTarget:self
activeServicesOnly:YES
longDescription:NO
format:nil]];
//Ensure our selection is still valid
[self ensureValidContactTypeSelection];
}
/*!
* @brief Called by AIServiceMenu to determine what services should be included
*/
- (BOOL)serviceMenuShouldIncludeService:(AIService *)inService
{
return (([AIAddressBookController propertyFromService:inService] &&
[[[adium.accountController accountsCompatibleWithService:inService] valueForKeyPath:@"@sum.online"] boolValue]) ? YES : NO);
}
/*!
* @breif Ensures that the selected contact type is valid, selecting another if it isn't
*/
- (void)ensureValidContactTypeSelection
{
NSInteger serviceIndex = -1;
//Force our menu to update.. it needs to be correctly validated for the code below to work
[[popUp_contactType menu] update];
//Find the menu item for our current service
if (service) serviceIndex = [popUp_contactType indexOfItemWithRepresentedObject:service];
//If our service is not available we'll have to pick another one
if (service && (serviceIndex == -1 || ![[popUp_contactType itemAtIndex:serviceIndex] isEnabled])) {
[self _setService:nil];
}
//If we don't have a service, pick the first availbale one
if (!service) {
[self _setService:[[[popUp_contactType menu] firstEnabledMenuItem] representedObject]];
}
//Update our menu and window for the current service
[popUp_contactType selectItemWithRepresentedObject:service];
[self configureForCurrentServiceType];
}
/*!
* @brief Configure any service-dependent controls in our window for the current service
*/
- (void)configureForCurrentServiceType
{
NSString *userNameLabel = [service userNameLabel];
[label_contactID setStringValue:[(userNameLabel ? userNameLabel :
AILocalizedString(@"Contact ID",nil)) stringByAppendingString:AILocalizedString(@":", "Colon which will be appended after a label such as 'User Name', before an input field")]];
}
/*!
* @brief User selected a new service type
*/
- (IBAction)selectServiceType:(id)sender
{
[self _setService:[[popUp_contactType selectedItem] representedObject]];
[self configureForCurrentServiceType];
}
/*!
* @brief Set the current service
*/
- (void)_setService:(AIService *)inService
{
if (inService != service) {
[service release];
service = [inService retain];
}
}
/*!
* @brief Set the current person
*/
- (void)_setPerson:(ABPerson *)inPerson
{
if (inPerson != person) {
[person release];
person = [inPerson retain];
}
}
/*!
* @brief Set the screen name/id
*/
- (void)_setScreenName:(NSString *)inName
{
if (inName != screenName) {
[screenName release];
screenName = [inName retain];
}
}
/*!
* @brief Set the carrying window. This is the window that our sheet is attached to.
*/
- (void)_setCarryingWindow:(NSWindow *)inWindow
{
if (carryingWindow != inWindow) {
[carryingWindow release];
carryingWindow = [inWindow retain];
}
}
// AIImageViewWithImagePicker Delegate ---------------------------------------------------------------------
#pragma mark AIImageViewWithImagePicker Delegate
- (void)imageViewWithImagePicker:(AIImageViewWithImagePicker *)sender didChangeToImageData:(NSData *)imageData
{
if (contactImage != imageData) {
[contactImage release];
contactImage = [imageData retain];
}
}
- (void)deleteInImageViewWithImagePicker:(AIImageViewWithImagePicker *)sender
{
[contactImage release]; contactImage = nil;
}
@end
#pragma mark -
@implementation NSObject (OWABSearchWindowControllerDelegate)
/*!
* @brief A delegate method that is sent when the user has selected a person/value.
*/
- (void)absearchWindowControllerDidSelectPerson:(OWABSearchWindowController *)controller
{
//Do nothing by default
}
@end