/* FILE: WindowController.m * * Project TChat * Class WindowController * Creator Chris B. Vetter * Maintainer Chris B. Vetter * Creation Date Mon Sep 11 15:17:32 CEST 2006 * * Copyright (c) 2006 * * TChat is free software under the terms of a dual BSD/LGPL license. * For a full copyright description, see the COPYRIGHT file. * ***************************************************************************/ // // Include // #include "main.h" #include "WindowController.h" #include #include #include #include #include #include #include #include #include // // Define // #define Localize(key) NSLocalizedString(key, @"") #define NC [NSNotificationCenter defaultCenter] // // Typedef // // // Public // // // Private // // // Private Interface // @interface WindowController (Private) @end // // Prototype // /*************************************************************************** ** ** Implementation ** */ @implementation WindowController static WindowController // fake 'shared' controller for -awakeFromNib... *wc = nil; // thanks GNUstep :-P /*************************************************************************** ** ** Factory Methods ** */ /*************************************************************************** ** ** Instance Methods ** */ /** * Description forthcoming * * */ - (id) initWithConnection: (NSFileHandle *) aFileHandle myName: (NSString *) me { if( (self = [super init]) ) { // // Stupid GNUstep calls -init during -awakeFromNib :-P // wc = self; [NC addObserver: self selector: @selector(receiveMessage:) name: NSFileHandleReadCompletionNotification object: fileHandle]; fileHandle = [aFileHandle retain]; myName = [me copy]; [fileHandle readInBackgroundAndNotify]; [NSBundle loadNibNamed: @"WindowController.gorm" owner: self]; return self; } // // That's it // return nil; } /*************************************************************************** ** ** Accessor Methods ** */ /*************************************************************************** ** ** Protocol Methods ** */ /*************************************************************************** ** ** Override Methods ** */ /** * Description forthcoming * * */ - (id) init { if( ! wc ) { [NSException raise: NSInternalInconsistencyException format: Localize(@"Use -initWithConnection:myName:")]; exit(EXIT_FAILURE); } // // That's it // return wc; } /** * Description forthcoming * * */ - (void) dealloc { { [[NSNotificationCenter defaultCenter] removeObserver: self]; [fileHandle closeFile]; [fileHandle release]; [myName release]; } [super dealloc]; // // That's it // return; } /** * Description forthcoming * * */ - (void) awakeFromNib { [inputField setEditable: YES]; [inputField setStringValue: @""]; [inputField setDelegate: self]; [inputField setTarget: self]; [inputField setAction: @selector(sendMessage:)]; [[textView enclosingScrollView] setScrollsDynamically: YES]; [window setInitialFirstResponder: inputField]; [window setTitle: Localize(@"Chat Window")]; [window setDelegate: self]; [window center]; // // That's it // return; } /** * Description forthcoming * * */ - (NSWindow *) window { // // That's it // return window; } /** * Description forthcoming * * */ - (void) showWindow: (id) sender { [inputField setStringValue: @""]; [window orderFrontRegardless]; [window display]; // // That's it // return; } /** * Description forthcoming * * */ - (void) windowWillClose: (NSNotification *) notification { [self release]; // // That's it // return; } /*************************************************************************** ** ** Private Methods ** */ /** * Description forthcoming * * */ - (void) postMessage: (NSString *) message from: (NSString *) person { NSString *s = nil; NSAttributedString *as = nil; s = [NSString stringWithFormat: @"%@: %@\n", person, message]; as = [[NSAttributedString alloc] initWithString: s]; // // Display the message... // [[textView textStorage] appendAttributedString: as]; [as release]; // // ...and scroll if necessary // [textView scrollPoint: NSMakePoint(0., [[textView string] length])]; // // FIXME: make 'inputField' the responder again, so we don't have to click // it after a message has been sent and displayed // // That's it // return; } /** * Description forthcoming * * */ - (void) sendMessage: (id) sender { NSString *message = nil; NSData *data = nil; // // Create the message and send it // message = [NSString stringWithFormat: @"_trystchat_:%@:%@", myName, [sender stringValue]]; data = [NSData dataWithBytes: [message UTF8String] length: [message length]]; [fileHandle writeData: data]; // // Display it in our own window... // [self postMessage: [sender stringValue] from: @"Me"]; // // ...and clear out 'inputField' // [sender setStringValue: @""]; // // That's it // return; } /** * Description forthcoming * * */ - (void) receiveMessage: (NSNotification *) notification { NSData *data = nil; NSString *message = nil; NSArray *components = nil; data = [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem]; // // Too short? // if( [data length] == 0 ) { [fileHandle readInBackgroundAndNotify]; return; } // // Nope, retrieve the message // message = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; // // FIXME: if the actual message part contains a colon, we're screwed... // components = [message componentsSeparatedByString: @":"]; if( [components count] != 3 ) { [fileHandle readInBackgroundAndNotify]; return; } // // Whatever it is, looks like it wasn't meant for us... // if( ! [[components objectAtIndex: 0] isEqualToString: @"_trystchat_"] ) { [fileHandle readInBackgroundAndNotify]; return; } // // Pop open the window // if( ! [[self window] isVisible] ) [self showWindow: nil]; // // ...and display the message // [self postMessage: [components objectAtIndex: 2] // FIXME: see above from: [components objectAtIndex: 1]]; // // Now check if there's more // [fileHandle readInBackgroundAndNotify]; // // That's it // return; } @end /*************************************************************************** ** ** Functions ** */ /* ** End of File. ** ****************************************************************************/