root/tags/2D9/JVChatConsolePanel.m

Revision 2558, 24.2 kB (checked in by eridius, 3 years ago)

Remove all trailing whitespace from lines
Remove indentation on blank lines

Line 
1 #import <ChatCore/MVChatConnection.h>
2 #import <ChatCore/MVChatPluginManager.h>
3 #import <ChatCore/NSMethodSignatureAdditions.h>
4
5 #import "JVChatConsolePanel.h"
6 #import "JVChatController.h"
7 #import "MVTextView.h"
8 #import "JVSplitView.h"
9
10 static NSString *JVToolbarToggleVerboseItemIdentifier = @"JVToolbarToggleVerboseItem";
11 static NSString *JVToolbarTogglePrivateMessagesItemIdentifier = @"JVToolbarTogglePrivateMessagesItem";
12 static NSString *JVToolbarClearItemIdentifier = @"JVToolbarClearItem";
13
14 @implementation JVChatConsolePanel
15 - (id) initWithConnection:(MVChatConnection *) connection {
16         if( ( self = [self init] ) ) {
17                 _sendHistory = [[NSMutableArray array] retain];
18                 [_sendHistory insertObject:[[[NSAttributedString alloc] initWithString:@""] autorelease] atIndex:0];
19
20                 _historyIndex = 0;
21                 _paused = NO;
22                 _forceSplitViewPosition = YES;
23
24                 _connection = [connection retain];
25                 _verbose = [[NSUserDefaults standardUserDefaults] boolForKey:@"JVChatVerboseConsoleMessages"];
26                 _ignorePRIVMSG = [[NSUserDefaults standardUserDefaults] boolForKey:@"JVChatConsolePanelIgnoreUserChatMessages"];
27
28                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _gotRawMessage: ) name:MVChatConnectionGotRawMessageNotification object:connection];
29                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( clearConsole: ) name:MVChatConnectionWillConnectNotification object:connection];
30
31                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _refreshIcon: ) name:MVChatConnectionDidConnectNotification object:connection];
32                 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _refreshIcon: ) name:MVChatConnectionDidDisconnectNotification object:connection];
33         }
34         return self;
35 }
36
37 - (void) awakeFromNib {
38         [send setUsesSystemCompleteOnTab:[[NSUserDefaults standardUserDefaults] boolForKey:@"JVUsePantherTextCompleteOnTab"]];
39         [send setContinuousSpellCheckingEnabled:NO];
40         [send setUsesFontPanel:NO];
41         [send setUsesRuler:NO];
42         [send setAllowsUndo:YES];
43         [send setImportsGraphics:NO];
44         [send reset:nil];
45
46         [display setContinuousSpellCheckingEnabled:NO];
47         [display setUsesFontPanel:NO];
48         [display setUsesRuler:NO];
49         [display setImportsGraphics:NO];
50
51         if( [[NSUserDefaults standardUserDefaults] boolForKey:@"JVChatInputAutoResizes"] )
52                 [(JVSplitView *)[[[send superview] superview] superview] setIsPaneSplitter:YES];
53 }
54
55 - (void) dealloc {
56         [[NSNotificationCenter defaultCenter] removeObserver:self];
57
58         [contents release];
59         [_sendHistory release];
60         [_connection release];
61
62         contents = nil;
63         _connection = nil;
64         _sendHistory = nil;
65         _windowController = nil;
66
67         [super dealloc];
68 }
69
70 - (NSString *) description {
71         return [NSString stringWithFormat:@"%@: %@", NSStringFromClass( [self class] ), [[self connection] server]];
72 }
73
74 #pragma mark -
75
76 - (IBAction) clearConsole:(id) sender {
77         [display setString:@""];
78 }
79
80 - (IBAction) toggleVerbose:(id) sender {
81         _verbose = ! _verbose;
82 }
83
84 - (IBAction) toggleMessages:(id) sender {
85         _ignorePRIVMSG = ! _ignorePRIVMSG;
86 }
87
88 - (IBAction) close:(id) sender {
89         [[JVChatController defaultManager] disposeViewController:self];
90 }
91
92 #pragma mark -
93
94 - (JVChatWindowController *) windowController {
95         return [[_windowController retain] autorelease];
96 }
97
98 - (void) setWindowController:(JVChatWindowController *) controller {
99         _windowController = controller;
100 }
101
102 #pragma mark -
103
104 - (NSView *) view {
105         if( ! _nibLoaded ) _nibLoaded = [NSBundle loadNibNamed:@"JVChatConsole" owner:self];
106         return contents;
107 }
108
109 - (NSResponder *) firstResponder {
110         return send;
111 }
112
113 - (NSToolbar *) toolbar {
114         NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"Console"];
115         [toolbar setDelegate:self];
116         [toolbar setAllowsUserCustomization:YES];
117         [toolbar setAutosavesConfiguration:YES];
118         return [toolbar autorelease];
119 }
120
121 #pragma mark -
122
123 - (BOOL) isEnabled {
124         return ! ( ! [[self connection] isConnected] && [[self connection] status] != MVChatConnectionConnectingStatus );
125 }
126
127 - (NSString *) title {
128         return [[self connection] server];
129 }
130
131 - (NSString *) windowTitle {
132         return [NSString stringWithFormat:NSLocalizedString( @"%@ - Console", "chat console - window title" ), [[self connection] server]];
133 }
134
135 - (NSString *) information {
136         if( ! [[self connection] isConnected] && [[self connection] status] != MVChatConnectionConnectingStatus )
137                 return NSLocalizedString( @"disconnected", "disconnected status info line in drawer" );
138         return nil;
139 }
140
141 - (NSString *) toolTip {
142         if( ! [[self connection] lag] ) return [self title];
143         return [NSString stringWithFormat:NSLocalizedString( @"%@\n%.3f seconds lag", "console tooltip witg lag (server delay) info in seconds" ), [self title], [[self connection] lag] / 1000.];
144 }
145
146 #pragma mark -
147
148 - (id <JVChatListItem>) parent {
149         return nil;
150 }
151
152 - (NSArray *) children {
153         return nil;
154 }
155
156 #pragma mark -
157
158 - (NSMenu *) menu {
159         NSMenu *menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
160         NSMenuItem *item = nil;
161
162         item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Get Info", "get info contextual menu item title" ) action:@selector( getInfo: ) keyEquivalent:@""] autorelease];
163         [item setTarget:_windowController];
164         [menu addItem:item];
165
166         item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Clear Display", "clear console contextual menu item title" ) action:@selector( clearConsole: ) keyEquivalent:@""] autorelease];
167         [item setTarget:self];
168         [menu addItem:item];
169
170         [menu addItem:[NSMenuItem separatorItem]];
171
172         item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Detach From Window", "detach from window contextual menu item title" ) action:@selector( detachView: ) keyEquivalent:@""] autorelease];
173         [item setRepresentedObject:self];
174         [item setTarget:[JVChatController defaultManager]];
175         [menu addItem:item];
176
177         item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString( @"Close", "close contextual menu item title" ) action:@selector( close: ) keyEquivalent:@""] autorelease];
178         [item setTarget:self];
179         [menu addItem:item];
180
181         return [[menu retain] autorelease];
182 }
183
184 - (NSImage *) icon {
185         return [NSImage imageNamed:@"console"];
186 }
187
188 #pragma mark -
189
190 - (NSString *) identifier {
191         return [NSString stringWithFormat:@"Console %@", [[self connection] server]];
192 }
193
194 - (MVChatConnection *) connection {
195         return _connection;
196 }
197
198 #pragma mark -
199
200 - (void) willSelect {
201         if( ! [[NSUserDefaults standardUserDefaults] boolForKey:@"JVChatInputAutoResizes"] ) {
202                 [(JVSplitView *)[[[send superview] superview] superview] setPositionUsingName:@"JVChatSplitViewPosition"];
203         } else [self textDidChange:nil];
204 }
205
206 #pragma mark -
207
208 - (void) pause {
209         if( [[self connection] type] == MVChatConnectionIRCType )
210                 _paused = YES;
211 }
212
213 - (void) resume {
214         _paused = NO;
215 }
216
217 - (BOOL) isPaused {
218         return _paused;
219 }
220
221 - (void) addMessageToDisplay:(NSString *) message asOutboundMessage:(BOOL) outbound {
222         NSAttributedString *msg = nil;
223         NSMutableString *strMsg = [[message mutableCopy] autorelease];
224         NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
225         NSMutableParagraphStyle *para = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
226         unsigned int numeric = 0;
227
228         if( [[self connection] type] == MVChatConnectionIRCType ) {
229                 if( ! [strMsg length] || ( _ignorePRIVMSG && [strMsg rangeOfString:@"PRIVMSG"].location != NSNotFound && [strMsg rangeOfString:@"\001"].location == NSNotFound ) )
230                         return;
231
232                 if( ! _verbose ) {
233                         [strMsg replaceOccurrencesOfString:@":" withString:@"" options:NSAnchoredSearch range:NSMakeRange( 0, 1 )];
234                         [strMsg replaceOccurrencesOfString:@" :" withString:@" " options:NSLiteralSearch range:NSMakeRange( 0, [strMsg length] )];
235                 }
236
237                 [strMsg replaceOccurrencesOfString:@"\r\n" withString:@"" options:NSAnchoredSearch | NSBackwardsSearch range:NSMakeRange( 0, [strMsg length] )];
238
239                 if( ! outbound && ! _verbose ) {
240                         NSMutableArray *parts = [[[strMsg componentsSeparatedByString:@" "] mutableCopy] autorelease];
241                         NSString *tempStr = nil;
242                         unsigned i = 0, c = 0;
243
244                         if( [parts count] >= 3 && [[parts objectAtIndex:2] isEqualToString:[[self connection] nickname]] )
245                                 [parts removeObjectAtIndex:2];
246
247                         if( [parts count] >= 2 && ( numeric = [[parts objectAtIndex:1] intValue] ) )
248                                 [parts removeObjectAtIndex:1];
249                         else if( [parts count] >= 2 && ( [[parts objectAtIndex:1] isEqualToString:@"PRIVMSG"] && [strMsg rangeOfString:@"\001"].location != NSNotFound && [strMsg rangeOfString:@" ACTION"].location == NSNotFound ) )
250                                 [parts replaceObjectAtIndex:1 withObject:@"CTCP REQUEST"];
251                         else if( [parts count] >= 2 && ( [[parts objectAtIndex:1] isEqualToString:@"NOTICE"] && [strMsg rangeOfString:@"\001"].location != NSNotFound ) )
252                                 [parts replaceObjectAtIndex:1 withObject:@"CTCP REPLY"];
253
254                         tempStr = [parts objectAtIndex:0];
255                         if( tempStr && [tempStr rangeOfString:@"@"].location == NSNotFound && [tempStr rangeOfString:@"."].location != NSNotFound && [NSURL URLWithString:[@"irc://" stringByAppendingString:tempStr]] ) {
256                                 [parts removeObjectAtIndex:0];
257                         } else if( [tempStr hasPrefix:[NSString stringWithFormat:@"%@!", [[self connection] nickname]]] ) {
258                                 [parts removeObjectAtIndex:0];
259                         }
260
261                         for( i = 0, c = [parts count]; i < c; i++ ) {
262                                 tempStr = [@"irc://" stringByAppendingString:[parts objectAtIndex:i]];
263                                 if( ( tempStr = [[NSURL URLWithString:tempStr] user] ) && [tempStr rangeOfString:@"!"].location != NSNotFound )
264                                         [parts replaceObjectAtIndex:i withObject:[tempStr substringToIndex:[tempStr rangeOfString:@"!"].location]];
265                         }
266
267                         strMsg = (NSMutableString *) [parts componentsJoinedByString:@" "];
268                         if( numeric ) strMsg = [NSString stringWithFormat:@"%03u: %@", numeric, strMsg];
269                 } else if( outbound && ! _verbose ) {
270                         if( [strMsg rangeOfString:@"NOTICE"].location != NSNotFound && [strMsg rangeOfString:@"\001"].location != NSNotFound ) {
271                                 [strMsg replaceOccurrencesOfString:@"NOTICE" withString:@"CTCP REPLY" options:NSAnchoredSearch range:NSMakeRange( 0, 6 )];
272                         } else if( [strMsg rangeOfString:@"PRIVMSG"].location != NSNotFound && [strMsg rangeOfString:@"\001"].location != NSNotFound && [strMsg rangeOfString:@" ACTION"].location == NSNotFound ) {
273                                 [strMsg replaceOccurrencesOfString:@"PRIVMSG" withString:@"CTCP REQUEST" options:NSAnchoredSearch range:NSMakeRange( 0, 7 )];
274                         }
275                 }
276         }
277
278         [para setParagraphSpacing:3.];
279         [para setMaximumLineHeight:9.];
280         if( ! outbound ) [para setMaximumLineHeight:9.];
281         else [para setMaximumLineHeight:11.];
282
283         if( outbound ) [attrs setObject:[NSFont boldSystemFontOfSize:11.] forKey:NSFontAttributeName];
284         else [attrs setObject:[[NSFontManager sharedFontManager] fontWithFamily:@"Monaco" traits:0 weight:5 size:9.] forKey:NSFontAttributeName];
285         [attrs setObject:para forKey:NSParagraphStyleAttributeName];
286
287         msg = [[[NSAttributedString alloc] initWithString:strMsg attributes:attrs] autorelease];
288         [[display textStorage] beginEditing];
289         if( [[display textStorage] length] )
290                 [display replaceCharactersInRange:NSMakeRange( [[display textStorage] length], 0 ) withString:@"\n"];
291         [[display textStorage] appendAttributedString:msg];
292         [[display textStorage] endEditing];
293         if( NSMinY( [display visibleRect] ) >= ( NSHeight( [display bounds] ) - ( NSHeight( [display visibleRect] ) * 1.1 ) ) )
294                 [display scrollRangeToVisible:NSMakeRange( [[display textStorage] length], 0 )];
295 }
296
297 #pragma mark -
298
299 - (void) send:(id) sender {
300         NSMutableAttributedString *subMsg = nil;
301         NSRange range;
302
303         if( ! [[self connection] isConnected] ) return;
304
305         [self resume];
306
307         _historyIndex = 0;
308         if( ! [[send textStorage] length] ) return;
309         if( [_sendHistory count] )
310                 [_sendHistory replaceObjectAtIndex:0 withObject:[[[NSAttributedString alloc] initWithString:@""] autorelease]];
311         [_sendHistory insertObject:[[[send textStorage] copy] autorelease] atIndex:1];
312         if( [_sendHistory count] > [[[NSUserDefaults standardUserDefaults] objectForKey:@"JVChatMaximumHistory"] unsignedIntValue] )
313                 [_sendHistory removeObjectAtIndex:[_sendHistory count] - 1];
314
315         while( [[send textStorage] length] ) {
316                 range = [[[send textStorage] string] rangeOfString:@"\n"];
317                 if( ! range.length ) range.location = [[send textStorage] length];
318                 subMsg = [[[[send textStorage] attributedSubstringFromRange:NSMakeRange( 0, range.location )] mutableCopy] autorelease];
319
320                 if( ( [subMsg length] >= 1 && range.length ) || ( [subMsg length] && ! range.length ) ) {
321                         if( [[subMsg string] hasPrefix:@"/"] ) {
322                                 NSScanner *scanner = [NSScanner scannerWithString:[subMsg string]];
323                                 NSString *command = nil;
324                                 NSAttributedString *arguments = nil;
325
326                                 [scanner scanString:@"/" intoString:nil];
327                                 [scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] intoString:&command];
328                                 if( [[subMsg string] length] >= [scanner scanLocation] + 1 )
329                                         [scanner setScanLocation:[scanner scanLocation] + 1];
330
331                                 arguments = [subMsg attributedSubstringFromRange:NSMakeRange( [scanner scanLocation], range.location - [scanner scanLocation] )];
332
333                                 NSMethodSignature *signature = [NSMethodSignature methodSignatureWithReturnAndArgumentTypes:@encode( BOOL ), @encode( NSString * ), @encode( NSAttributedString * ), @encode( MVChatConnection * ), @encode( id ), nil];
334                                 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
335
336                                 [invocation setSelector:@selector( processUserCommand:withArguments:toConnection:inView: )];
337                                 [invocation setArgument:&command atIndex:2];
338                                 [invocation setArgument:&arguments atIndex:3];
339                                 [invocation setArgument:&_connection atIndex:4];
340                                 [invocation setArgument:&self atIndex:5];
341
342                                 NSArray *results = [[MVChatPluginManager defaultManager] makePluginsPerformInvocation:invocation stoppingOnFirstSuccessfulReturn:YES];
343
344                                 if( ! [[results lastObject] boolValue] )
345                                         [[self connection] sendRawMessage:[command stringByAppendingFormat:@" %@", [arguments string]]];
346                         } else {
347                                 [[self connection] sendRawMessage:[subMsg string]];
348                         }
349                 }
350                 if( range.length ) range.location++;
351                 [[send textStorage] deleteCharactersInRange:NSMakeRange( 0, range.location )];
352         }
353
354         [send reset:nil];
355         [self textDidChange:nil];
356         [display scrollRangeToVisible:NSMakeRange( [[display textStorage] length], 0 )];
357 }
358
359 - (BOOL) textView:(NSTextView *) textView enterKeyPressed:(NSEvent *) event {
360         [self send:nil];
361         return YES;
362 }
363
364 - (BOOL) textView:(NSTextView *) textView returnKeyPressed:(NSEvent *) event {
365         [self send:nil];
366         return YES;
367 }
368
369 - (BOOL) upArrowKeyPressed {
370         if( ! _historyIndex && [_sendHistory count] )
371                 [_sendHistory replaceObjectAtIndex:0 withObject:[[[send textStorage] copy] autorelease]];
372         _historyIndex++;
373         if( _historyIndex >= [_sendHistory count] ) {
374                 _historyIndex = [_sendHistory count] - 1;
375                 if( (signed) _historyIndex < 0 ) _historyIndex = 0;
376                 return YES;
377         }
378         [send reset:nil];
379         [[send textStorage] insertAttributedString:[_sendHistory objectAtIndex:_historyIndex] atIndex:0];
380         return YES;
381 }
382
383 - (BOOL) downArrowKeyPressed {
384         if( ! _historyIndex && [_sendHistory count] )
385                 [_sendHistory replaceObjectAtIndex:0 withObject:[[[send textStorage] copy] autorelease]];
386         if( [[send textStorage] length] ) _historyIndex--;
387         if( _historyIndex < 0 ) {
388                 [send reset:nil];
389                 _historyIndex = -1;
390                 return YES;
391         } else if( ! [_sendHistory count] ) {
392                 _historyIndex = 0;
393                 return YES;
394         }
395         [send reset:nil];
396         [[send textStorage] insertAttributedString:[_sendHistory objectAtIndex:_historyIndex] atIndex:0];
397         return YES;
398 }
399
400 - (BOOL) textView:(NSTextView *) textView functionKeyPressed:(NSEvent *) event {
401         unichar chr = 0;
402
403         if( [[event charactersIgnoringModifiers] length] ) {
404                 chr = [[event charactersIgnoringModifiers] characterAtIndex:0];
405         } else return NO;
406
407         // exclude device-dependent flags, caps-lock and fn key (necessary for pg up/pg dn/home/end on portables)
408         if( [event modifierFlags] & ~( NSFunctionKeyMask | NSNumericPadKeyMask | NSAlphaShiftKeyMask | 0xffff ) ) return NO;
409
410         if( chr == NSUpArrowFunctionKey ) {
411                 return [self upArrowKeyPressed];
412         } else if( chr == NSDownArrowFunctionKey ) {
413                 return [self downArrowKeyPressed];
414         }
415
416         return NO;
417 }
418
419 - (NSArray *) completionsFor:(NSString *) inFragment {
420         return nil;
421 }
422
423 - (BOOL) textView:(NSTextView *) textView escapeKeyPressed:(NSEvent *) event {
424         [send reset:nil];
425         return YES;
426 }
427
428 - (void) textDidChange:(NSNotification *) notification {
429         _historyIndex = 0;
430
431         if( ! [[NSUserDefaults standardUserDefaults] boolForKey:@"JVChatInputAutoResizes"] )
432                 return;
433
434         // We need to resize the textview to fit the content.
435         // The scroll views are two superviews up: NSTextView -> NSClipView -> NSScrollView
436         NSSplitView *splitView = (NSSplitView *)[[[send superview] superview] superview];
437         NSRect splitViewFrame = [splitView frame];
438         NSSize contentSize = [send minimumSizeForContent];
439         NSRect sendFrame = [[[send superview] superview] frame];
440         float dividerThickness = [splitView dividerThickness];
441         float maxContentHeight = ( NSHeight( splitViewFrame ) - dividerThickness - 75. );
442         float newContentHeight =  MIN( maxContentHeight, MAX( 25., contentSize.height + 8. ) );
443
444         if( newContentHeight == NSHeight( sendFrame ) ) return;
445
446         NSRect displayFrame = [[[display superview] superview] frame];
447
448         // Set size of the web view to the maximum size possible
449         displayFrame.size.height = NSHeight( splitViewFrame ) - dividerThickness - newContentHeight;
450         displayFrame.origin = NSMakePoint( 0., 0. );
451
452         // Keep the send box the same size
453         sendFrame.size.height = newContentHeight;
454         sendFrame.origin.y = NSHeight( displayFrame ) + dividerThickness;
455
456         [[display window] disableFlushWindow]; // prevent any draw (white) flashing that might occur
457
458         NSScroller *scroller = [(NSScrollView *)[[display superview] superview] verticalScroller];
459         if( ! scroller || [scroller floatValue] == 1. ) _scrollerIsAtBottom = YES;
460         else _scrollerIsAtBottom = NO;
461
462         // Commit the changes
463         [[[send superview] superview] setFrame:sendFrame];
464         [[[display superview] superview] setFrame:displayFrame];
465
466         if( _scrollerIsAtBottom )
467                 [display scrollRangeToVisible:NSMakeRange( [[display textStorage] length], 0 )];
468
469         [display displayIfNeeded]; // makes the WebView draw correctly
470         [splitView setNeedsDisplay:YES]; // makes the divider redraw correctly later
471         [[display window] enableFlushWindow]; // flush everything we have drawn
472 }
473
474 #pragma mark -
475 #pragma mark Scripting Support
476
477 - (NSNumber *) uniqueIdentifier {
478         return [NSNumber numberWithUnsignedInt:(unsigned long) self];
479 }
480
481 - (NSWindow *) window {
482         return [[self windowController] window];
483 }
484
485 - (id) valueForUndefinedKey:(NSString *) key {
486         if( [NSScriptCommand currentCommand] ) {
487                 [[NSScriptCommand currentCommand] setScriptErrorNumber:1000];
488                 [[NSScriptCommand currentCommand] setScriptErrorString:[NSString stringWithFormat:@"The panel id %@ doesn't have the \"%@\" property.", [self uniqueIdentifier], key]];
489                 return nil;
490         }
491
492         return [super valueForUndefinedKey:key];
493 }
494
495 - (void) setValue:(id) value forUndefinedKey:(NSString *) key {
496         if( [NSScriptCommand currentCommand] ) {
497                 [[NSScriptCommand currentCommand] setScriptErrorNumber:1000];
498                 [[NSScriptCommand currentCommand] setScriptErrorString:[NSString stringWithFormat:@"The \"%@\" property of panel id %@ is read only.", key, [self uniqueIdentifier]]];
499                 return;
500         }
501
502         [super setValue:value forUndefinedKey:key];
503 }
504
505 #pragma mark -
506 #pragma mark Toolbar Support
507
508 - (NSToolbarItem *) toolbar:(NSToolbar *) toolbar itemForItemIdentifier:(NSString *) identifier willBeInsertedIntoToolbar:(BOOL) willBeInserted {
509         NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:identifier] autorelease];
510         if( [identifier isEqual:JVToolbarToggleChatDrawerItemIdentifier] ) {
511                 toolbarItem = [_windowController toggleChatDrawerToolbarItem];
512         } else if( [identifier isEqual:JVToolbarClearItemIdentifier] ) {
513                 [toolbarItem setLabel:NSLocalizedString( @"Clear", "clear console toolbar button name" )];
514                 [toolbarItem setPaletteLabel:NSLocalizedString( @"Clear Console", "clear console toolbar customize palette name" )];
515
516                 [toolbarItem setToolTip:NSLocalizedString( @"Clear Console", "clear console tooltip" )];
517                 [toolbarItem setImage:[NSImage imageNamed:@"clear"]];
518
519                 [toolbarItem setTarget:self];
520                 [toolbarItem setAction:@selector( clearConsole: )];
521         } else if( [identifier isEqual:JVToolbarToggleVerboseItemIdentifier] ) {
522                 [toolbarItem setLabel:NSLocalizedString( @"Verbose", "verbose toolbar button name" )];
523                 [toolbarItem setPaletteLabel:NSLocalizedString( @"Toggle Verbose", "toggle verbose toolbar customize palette name" )];
524
525                 [toolbarItem setToolTip:NSLocalizedString( @"Toggle Verbose Output", "toggle verbose output tooltip" )];
526                 [toolbarItem setImage:[NSImage imageNamed:@"reveal"]];
527
528                 [toolbarItem setTarget:self];
529                 [toolbarItem setAction:@selector( toggleVerbose: )];
530         } else if( [identifier isEqual:JVToolbarTogglePrivateMessagesItemIdentifier] ) {
531                 [toolbarItem setLabel:NSLocalizedString( @"Messages", "toggle private messages toolbar button name" )];
532                 [toolbarItem setPaletteLabel:NSLocalizedString( @"Toggle Messages", "toggle private messages toolbar customize palette name" )];
533
534                 [toolbarItem setToolTip:NSLocalizedString( @"Toggle Private Messages Output", "toggle private messages output tooltip" )];
535                 [toolbarItem setImage:[NSImage imageNamed:@"room"]];
536
537                 [toolbarItem setTarget:self];
538                 [toolbarItem setAction:@selector( toggleMessages: )];
539         } else toolbarItem = nil;
540         return toolbarItem;
541 }
542
543 - (NSArray *) toolbarDefaultItemIdentifiers:(NSToolbar *) toolbar {
544         NSArray *list = [NSArray arrayWithObjects:JVToolbarToggleChatDrawerItemIdentifier, JVToolbarClearItemIdentifier, nil];
545         return [[list retain] autorelease];
546 }
547
548 - (NSArray *) toolbarAllowedItemIdentifiers:(NSToolbar *) toolbar {
549         NSArray *list = [NSArray arrayWithObjects:JVToolbarToggleChatDrawerItemIdentifier, JVToolbarToggleVerboseItemIdentifier, JVToolbarTogglePrivateMessagesItemIdentifier, JVToolbarClearItemIdentifier, NSToolbarCustomizeToolbarItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, NSToolbarSeparatorItemIdentifier, nil];
550         return [[list retain] autorelease];
551 }
552
553 #pragma mark -
554 #pragma mark SplitView Support
555
556 - (float) splitView:(NSSplitView *) splitView constrainSplitPosition:(float) proposedPosition ofSubviewAt:(int) index {
557         if( [[NSUserDefaults standardUserDefaults] boolForKey:@"JVChatInputAutoResizes"] )
558                 return ( NSHeight( [[[splitView subviews] objectAtIndex:index] frame] ) ); // prevents manual resize
559         return proposedPosition;
560 }
561
562 - (void) splitViewDidResizeSubviews:(NSNotification *) notification {
563         // Cache the height of the send box so we can keep it constant during window resizes.
564         NSRect sendFrame = [[[send superview] superview] frame];
565         _sendHeight = sendFrame.size.height;
566
567         if( _scrollerIsAtBottom )
568                 [display scrollRangeToVisible:NSMakeRange( [[display textStorage] length], 0 )];
569
570         if( ! _forceSplitViewPosition && ! [[NSUserDefaults standardUserDefaults] boolForKey:@"JVChatInputAutoResizes"] )
571                 [(JVSplitView *)[notification object] savePositionUsingName:@"JVChatSplitViewPosition"];
572
573         _forceSplitViewPosition = NO;
574 }
575
576 - (void) splitViewWillResizeSubviews:(NSNotification *) notification {
577         NSScroller *scroller = [(NSScrollView *)[[display superview] superview] verticalScroller];
578         if( ! scroller || [scroller floatValue] == 1. ) _scrollerIsAtBottom = YES;
579         else _scrollerIsAtBottom = NO;
580 }
581
582 - (void) splitView:(NSSplitView *) sender resizeSubviewsWithOldSize:(NSSize) oldSize {
583         float dividerThickness = [sender dividerThickness];
584         NSRect newFrame = [sender frame];
585
586         // Keep the size of the send box constant during window resizes
587
588         // We need to resize the scroll view frames of the webview and the textview.
589         // The scroll views are two superviews up: NSTextView(WebView) -> NSClipView -> NSScrollView
590         NSRect sendFrame = [[[send superview] superview] frame];
591         NSRect displayFrame = [[[display superview] superview] frame];
592
593         // Set size of the web view to the maximum size possible
594         displayFrame.size.height = NSHeight( newFrame ) - dividerThickness - _sendHeight;
595         displayFrame.size.width = NSWidth( newFrame );
596         displayFrame.origin = NSMakePoint( 0., 0. );
597
598         // Keep the send box the same size
599         sendFrame.size.height = _sendHeight;
600         sendFrame.size.width = NSWidth( newFrame );
601         sendFrame.origin.y = NSHeight( displayFrame ) + dividerThickness;
602
603         // Commit the changes
604         [[[send superview] superview] setFrame:sendFrame];
605         [[[display superview] superview] setFrame:displayFrame];
606 }
607 @end
608
609 #pragma mark -
610
611 @implementation JVChatConsolePanel (JVChatConsolePanelPrivate)
612 - (void) _gotRawMessage:(NSNotification *) notification {
613         if( _paused ) return;
614         [self addMessageToDisplay:[[notification userInfo] objectForKey:@"message"] asOutboundMessage:[[[notification userInfo] objectForKey:@"outbound"] boolValue]];
615 }
616
617 - (void) _refreshIcon:(NSNotification *) notification {
618         [_windowController reloadListItem:self andChildren:NO];
619 }
620 @end
Note: See TracBrowser for help on using the browser.