293 lines
9.3 KiB
Objective-C
293 lines
9.3 KiB
Objective-C
//
|
|
// MGMContactsController.m
|
|
// VoiceMac
|
|
//
|
|
// Created by Mr. Gecko on 9/12/10.
|
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
|
|
//
|
|
// Permission to use, copy, modify, and/or distribute this software for any purpose
|
|
// with or without fee is hereby granted, provided that the above copyright notice
|
|
// and this permission notice appear in all copies.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
// FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
|
|
// OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
// ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
//
|
|
|
|
#import "MGMContactsController.h"
|
|
#import "MGMController.h"
|
|
#import "MGMViewCell.h"
|
|
#import "MGMContactView.h"
|
|
#import "MGMPhoneFeild.h"
|
|
#import <VoiceBase/VoiceBase.h>
|
|
|
|
NSString *MGMContactsWindowOpen = @"MGMContactsWindowOpen";
|
|
|
|
@implementation MGMContactsController
|
|
- (id)initWithController:(MGMController *)theController {
|
|
if ((self = [super init])) {
|
|
controller = theController;
|
|
filterLock = [NSLock new];
|
|
filterWaiting = 0;
|
|
contactViews = [NSMutableArray new];
|
|
contactsCount = 0;
|
|
|
|
hasCustomIncomingIcon = [[controller themeManager] hasCustomIncomingIcon];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatedTheme:) name:MGMTUpdatedSMSThemeNotification object:[controller themeManager]];
|
|
}
|
|
return self;
|
|
}
|
|
- (void)awakeFromNib {
|
|
[[[contactsTable tableColumns] objectAtIndex:0] setDataCell:[[MGMViewCell new] autorelease]];
|
|
[contactsTable setTarget:self];
|
|
[contactsTable setDoubleAction:@selector(runAction:)];
|
|
[contactsWindow setExcludedFromWindowsMenu:YES];
|
|
|
|
phoneFieldView = [[MGMPhoneFieldView alloc] initWithFrame:NSZeroRect];
|
|
[phoneFieldView setFieldEditor:YES];
|
|
[phoneFieldView setPhoneDelegate:self];
|
|
[phoneField setDelegate:self];
|
|
[self filterContacts];
|
|
}
|
|
- (void)dealloc {
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
[contactsWindow close];
|
|
[filterLock lock];
|
|
[filterLock unlock];
|
|
[filterLock release];
|
|
[contactViews release];
|
|
[super dealloc];
|
|
}
|
|
|
|
- (MGMController *)controller {
|
|
return controller;
|
|
}
|
|
- (NSString *)menuTitle {
|
|
return @"Contacts";
|
|
}
|
|
- (NSArray *)contactViews {
|
|
return contactViews;
|
|
}
|
|
- (NSWindow *)contactsWindow {
|
|
return contactsWindow;
|
|
}
|
|
- (NSTableView *)contactsTable {
|
|
return contactsTable;
|
|
}
|
|
- (MGMPhoneField *)phoneField {
|
|
return phoneField;
|
|
}
|
|
- (void)showContactsWindow {
|
|
|
|
}
|
|
- (MGMContacts *)contacts {
|
|
return nil;
|
|
}
|
|
- (NSString *)filterString {
|
|
return [phoneField stringValue];
|
|
}
|
|
|
|
- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
|
|
if (commandSelector==@selector(insertNewline:)) {
|
|
[self runAction:self];
|
|
return YES;
|
|
} else if (commandSelector==@selector(moveDown:)) {
|
|
[self selectFirstContact];
|
|
return YES;
|
|
} else if (commandSelector==@selector(deleteToBeginningOfLine:)) {
|
|
[self performSelector:@selector(filterContacts) withObject:nil afterDelay:0.2];
|
|
return NO;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
- (void)reloadData {
|
|
while ([[contactsTable subviews] count]>0)
|
|
[[[contactsTable subviews] lastObject] removeFromSuperviewWithoutNeedingDisplay];
|
|
[contactsTable reloadData];
|
|
[contactsTable display];
|
|
}
|
|
- (int)numberOfRowsInTableView:(NSTableView *)tableView {
|
|
return contactsCount;
|
|
}
|
|
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row {
|
|
return nil;
|
|
}
|
|
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(int)row {
|
|
if (row>=contactsCount) return;
|
|
[self checkContactRow:row];
|
|
[filterLock lock];
|
|
if ((row-contactsVisible.location)<[contactViews count])
|
|
[(MGMViewCell *)cell addSubview:[contactViews objectAtIndex:row-contactsVisible.location]];
|
|
[filterLock unlock];
|
|
}
|
|
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row {
|
|
if (row>=contactsCount) return NO;
|
|
[self checkContactRow:row];
|
|
[phoneField setStringValue:[[[[contactViews objectAtIndex:row-contactsVisible.location] contact] objectForKey:MGMCNumber] readableNumber]];
|
|
return YES;
|
|
}
|
|
- (void)checkContactRow:(int)row {
|
|
if (!NSLocationInRange(row, contactsVisible)) {
|
|
int maxResults = [[self contacts] maxResults];
|
|
int page = (row/maxResults)+1;
|
|
contactsLoading.location = ((page==1 ? 1 : page-1)*maxResults)-maxResults;
|
|
contactsLoading.length = (row<(maxResults-3) ? maxResults : maxResults*2);
|
|
[self loadContacts:NO];
|
|
}
|
|
}
|
|
|
|
- (void)updatedTheme:(NSNotification *)theNotification {
|
|
BOOL customIncoming = [[controller themeManager] hasCustomIncomingIcon];
|
|
if (hasCustomIncomingIcon!=customIncoming || customIncoming) {
|
|
hasCustomIncomingIcon = customIncoming;
|
|
[self reloadData];
|
|
}
|
|
}
|
|
|
|
- (void)filterContacts {
|
|
[NSThread detachNewThreadSelector:@selector(backgroundFilter) toTarget:self withObject:nil];
|
|
}
|
|
- (void)backgroundFilter {
|
|
if (contactsWindow==nil) return;
|
|
if (filterWaiting>=1)
|
|
return;
|
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
|
filterWaiting++;
|
|
[filterLock lock];
|
|
filterWaiting--;
|
|
contactsCount = 0;
|
|
[contactViews removeAllObjects];
|
|
[contactsMatchString release];
|
|
contactsMatchString = [[self filterString] copy];
|
|
int count = [[[self contacts] countContactsMatching:contactsMatchString] intValue];
|
|
[contactsTable scrollRowToVisible:0];
|
|
|
|
contactsLoading.location = 0;
|
|
contactsLoading.length = 0;
|
|
contactsVisible.location = 0;
|
|
contactsVisible.length = [[self contacts] maxResults];
|
|
|
|
NSArray *newContacts = [[self contacts] contactsMatching:contactsMatchString page:1];
|
|
for (int i=0; i<[newContacts count]; i++) {
|
|
MGMContactView *contact = [MGMContactView viewWithFrame:NSMakeRect(0, 0, 200, 64) themeManager:[controller themeManager]];
|
|
[contact setContact:[newContacts objectAtIndex:i]];
|
|
[contactViews addObject:contact];
|
|
}
|
|
contactsCount = count;
|
|
[filterLock unlock];
|
|
if (contactsWindow==nil) return;
|
|
[self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
|
|
[pool drain];
|
|
}
|
|
- (void)loadContacts:(BOOL)updatingCount {
|
|
if (contactsWindow==nil) return;
|
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
|
[filterLock lock];
|
|
int count = 0;
|
|
if (updatingCount) {
|
|
count = [[[self contacts] countContactsMatching:contactsMatchString] intValue];
|
|
contactsCount = 0;
|
|
}
|
|
int maxResults = [[self contacts] maxResults];
|
|
[contactViews removeAllObjects];
|
|
int page = contactsLoading.location/maxResults;
|
|
int times = contactsLoading.length/maxResults;
|
|
for (int t=0; t<times; t++) {
|
|
page++;
|
|
NSArray *newContacts = [[self contacts] contactsMatching:contactsMatchString page:page];
|
|
for (int i=0; i<[newContacts count]; i++) {
|
|
MGMContactView *contact = [MGMContactView viewWithFrame:NSMakeRect(0, 0, 200, 64) themeManager:[controller themeManager]];
|
|
[contact setContact:[newContacts objectAtIndex:i]];
|
|
[contactViews addObject:contact];
|
|
}
|
|
}
|
|
contactsVisible = contactsLoading;
|
|
if (updatingCount)
|
|
contactsCount = count;
|
|
[filterLock unlock];
|
|
if (contactsWindow==nil) return;
|
|
[self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
|
|
[pool drain];
|
|
}
|
|
- (void)selectFirstContact {
|
|
[contactsWindow makeFirstResponder:contactsTable];
|
|
[contactsTable selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
|
|
[self tableView:contactsTable shouldSelectRow:0];
|
|
}
|
|
|
|
- (void)updatedContacts {
|
|
if (contactsWindow==nil) return;
|
|
contactsLoading = contactsVisible;
|
|
[self loadContacts:YES];
|
|
}
|
|
|
|
- (NSString *)areaCode {
|
|
return nil;
|
|
}
|
|
- (NSString *)currentPhoneNumber {
|
|
NSString *phoneNumber = nil;
|
|
if (phoneNumber==nil && ![[phoneField stringValue] isPhoneComplete]) {
|
|
if ([contactViews count]>0) {
|
|
[self selectFirstContact];
|
|
} else {
|
|
return nil;
|
|
}
|
|
}
|
|
if (phoneNumber==nil)
|
|
phoneNumber = [[phoneField stringValue] phoneFormatWithAreaCode:[self areaCode]];
|
|
return phoneNumber;
|
|
}
|
|
- (IBAction)runAction:(id)sender {
|
|
|
|
}
|
|
- (IBAction)call:(id)sender {
|
|
|
|
}
|
|
|
|
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)anObject {
|
|
if ([anObject isKindOfClass:[MGMPhoneField class]]) {
|
|
return phoneFieldView;
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (void)windowDidBecomeKey:(NSNotification *)notification {
|
|
[controller contactsControllerBecameCurrent:self];
|
|
}
|
|
- (void)windowWillClose:(NSNotification *)notification {
|
|
[contactsWindow setDelegate:nil];
|
|
contactsWindow = nil;
|
|
[contactViews removeAllObjects];
|
|
contactsCount = 0;
|
|
contactsTable = nil;
|
|
phoneFieldView = nil;
|
|
phoneField = nil;
|
|
}
|
|
@end
|
|
|
|
@implementation MGMContactsTableView
|
|
- (void)keyDown:(NSEvent *)theEvent {
|
|
int keyCode = [theEvent keyCode];
|
|
if (keyCode==36 || keyCode==76) {
|
|
[contactsController runAction:self];
|
|
} else if (keyCode==48) {
|
|
[[self window] makeFirstResponder:[contactsController phoneField]];
|
|
} else {
|
|
[super keyDown:theEvent];
|
|
}
|
|
}
|
|
- (void)copy:(id)sender {
|
|
if ([self selectedRow]==-1) {
|
|
NSBeep();
|
|
return;
|
|
}
|
|
NSString *phoneNumber = [[[[contactsController contactViews] objectAtIndex:[self selectedRow]] contact] objectForKey:MGMCNumber];
|
|
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
|
|
[pasteBoard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:nil];
|
|
[pasteBoard setString:[phoneNumber readableNumber] forType:NSStringPboardType];
|
|
}
|
|
@end |