1/** <title>NSResponder</title> 2 3 <abstract>Abstract class which is basis of command and event processing</abstract> 4 5 Copyright (C) 1996,1999 Free Software Foundation, Inc. 6 7 Author: Scott Christley <scottc@net-community.com> 8 Date: 1996 9 10 This file is part of the GNUstep GUI Library. 11 12 This library is free software; you can redistribute it and/or 13 modify it under the terms of the GNU Lesser General Public 14 License as published by the Free Software Foundation; either 15 version 2 of the License, or (at your option) any later version. 16 17 This library is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 Lesser General Public License for more details. 21 22 You should have received a copy of the GNU Lesser General Public 23 License along with this library; see the file COPYING.LIB. 24 If not, see <http://www.gnu.org/licenses/> or write to the 25 Free Software Foundation, 51 Franklin Street, Fifth Floor, 26 Boston, MA 02110-1301, USA. 27*/ 28 29#include "config.h" 30#import <Foundation/NSCoder.h> 31#import <Foundation/NSDebug.h> 32#import <Foundation/NSInvocation.h> 33#import "AppKit/NSResponder.h" 34#import "AppKit/NSApplication.h" 35#import "AppKit/NSMenu.h" 36#import "AppKit/NSEvent.h" 37#import "AppKit/NSGraphics.h" 38#import "AppKit/NSHelpManager.h" 39#import "AppKit/NSInputManager.h" 40 41@implementation NSResponder 42 43/* 44 * Class methods 45 */ 46+ (void) initialize 47{ 48 if (self == [NSResponder class]) 49 { 50 [self setVersion: 1]; 51 52 /* Gets the current input manager - this forces it to read the 53 key binding files at this stage. */ 54 [NSInputManager currentInputManager]; 55 } 56} 57 58/* 59 * Instance methods 60 */ 61/* 62 * Managing the next responder 63 */ 64- (NSResponder*) nextResponder 65{ 66 return _next_responder; 67} 68 69- (void) setNextResponder: (NSResponder*)aResponder 70{ 71 _next_responder = aResponder; 72} 73 74/** 75 * Returns YES if the receiver is able to become the first responder, 76 * NO otherwise. 77 */ 78- (BOOL) acceptsFirstResponder 79{ 80 return NO; 81} 82 83- (BOOL) becomeFirstResponder 84{ 85 return YES; 86} 87 88- (BOOL) resignFirstResponder 89{ 90 return YES; 91} 92 93/* 94 * Aid event processing 95 */ 96- (BOOL) performKeyEquivalent: (NSEvent*)theEvent 97{ 98 return NO; 99} 100 101/** 102 * If the receiver responds to anAction, it performs that method with 103 * anObject as its argument, discards any return value, and return YES.<br /> 104 * Otherwise, the next responder in the chain is asked to perform 105 * anAction and the result of that is returned.<br /> 106 * If no responder in the chain is able to respond to anAction, then 107 * NO is returned. 108 */ 109- (BOOL) tryToPerform: (SEL)anAction with: (id)anObject 110{ 111 /* Can we perform the action -then do it */ 112 if ([self respondsToSelector: anAction]) 113 { 114 IMP actionIMP = [self methodForSelector: anAction]; 115 if (0 != actionIMP) 116 { 117 actionIMP(self, anAction, anObject); 118 return YES; 119 } 120 return YES; 121 } 122 else 123 { 124 /* If we cannot perform then try the next responder */ 125 if (!_next_responder) 126 return NO; 127 else 128 return [_next_responder tryToPerform: anAction with: anObject]; 129 } 130} 131 132- (BOOL) performMnemonic: (NSString*)aString 133{ 134 return NO; 135} 136 137- (void) interpretKeyEvents:(NSArray*)eventArray 138{ 139 [[NSInputManager currentInputManager] handleKeyboardEvents: eventArray 140 client: self]; 141} 142 143- (void) flushBufferedKeyEvents 144{ 145} 146 147- (void) doCommandBySelector:(SEL)aSelector 148{ 149 if (![self tryToPerform: aSelector with: nil]) 150 { 151 NSBeep(); 152 } 153} 154 155- (void) insertText: (id)aString 156{ 157 if (_next_responder) 158 [_next_responder insertText: aString]; 159 else 160 { 161 NSBeep (); 162 } 163} 164 165 166/* 167 * Forwarding event messages 168 */ 169- (void) flagsChanged: (NSEvent*)theEvent 170{ 171 if (_next_responder) 172 [_next_responder flagsChanged: theEvent]; 173 else 174 [self noResponderFor: @selector(flagsChanged:)]; 175} 176 177- (void) helpRequested: (NSEvent*)theEvent 178{ 179 if ([[NSHelpManager sharedHelpManager] 180 showContextHelpForObject: self 181 locationHint: [theEvent locationInWindow]] == NO) 182 { 183 if (_next_responder) 184 { 185 [_next_responder helpRequested: theEvent]; 186 return; 187 } 188 } 189 [NSHelpManager setContextHelpModeActive: NO]; 190} 191 192- (void) keyDown: (NSEvent*)theEvent 193{ 194 if (_next_responder) 195 [_next_responder keyDown: theEvent]; 196 else 197 [self noResponderFor: @selector(keyDown:)]; 198} 199 200- (void) keyUp: (NSEvent*)theEvent 201{ 202 if (_next_responder) 203 [_next_responder keyUp: theEvent]; 204 else 205 [self noResponderFor: @selector(keyUp:)]; 206} 207 208- (void) otherMouseDown: (NSEvent*)theEvent 209{ 210 if (_next_responder) 211 [_next_responder otherMouseDown: theEvent]; 212 else 213 [self noResponderFor: @selector(otherMouseDown:)]; 214} 215 216- (void) otherMouseDragged: (NSEvent*)theEvent 217{ 218 if (_next_responder) 219 [_next_responder otherMouseDragged: theEvent]; 220 else 221 [self noResponderFor: @selector(otherMouseDragged:)]; 222} 223 224- (void) otherMouseUp: (NSEvent*)theEvent 225{ 226 if (_next_responder) 227 [_next_responder otherMouseUp: theEvent]; 228 else 229 [self noResponderFor: @selector(otherMouseUp:)]; 230} 231 232- (void) mouseDown: (NSEvent*)theEvent 233{ 234 if (_next_responder) 235 [_next_responder mouseDown: theEvent]; 236 else 237 [self noResponderFor: @selector(mouseDown:)]; 238} 239 240- (void) mouseDragged: (NSEvent*)theEvent 241{ 242 if (_next_responder) 243 [_next_responder mouseDragged: theEvent]; 244 else 245 [self noResponderFor: @selector(mouseDragged:)]; 246} 247 248- (void) mouseEntered: (NSEvent*)theEvent 249{ 250 if (_next_responder) 251 [_next_responder mouseEntered: theEvent]; 252 else 253 [self noResponderFor: @selector(mouseEntered:)]; 254} 255 256- (void) mouseExited: (NSEvent*)theEvent 257{ 258 if (_next_responder) 259 [_next_responder mouseExited: theEvent]; 260 else 261 [self noResponderFor: @selector(mouseExited:)]; 262} 263 264- (void) mouseMoved: (NSEvent*)theEvent 265{ 266 if (_next_responder) 267 [_next_responder mouseMoved: theEvent]; 268 else 269 [self noResponderFor: @selector(mouseMoved:)]; 270} 271 272- (void) mouseUp: (NSEvent*)theEvent 273{ 274 if (_next_responder) 275 [_next_responder mouseUp: theEvent]; 276 else 277 [self noResponderFor: @selector(mouseUp:)]; 278} 279 280- (void) noResponderFor: (SEL)eventSelector 281{ 282 /* Only beep for key down events */ 283 if (sel_isEqual(eventSelector, @selector(keyDown:))) 284 NSBeep(); 285} 286 287- (void) rightMouseDown: (NSEvent*)theEvent 288{ 289 if (_next_responder != nil) 290 [_next_responder rightMouseDown: theEvent]; 291 else 292 [self noResponderFor: @selector(rightMouseDown:)]; 293} 294 295- (void) rightMouseDragged: (NSEvent*)theEvent 296{ 297 if (_next_responder) 298 [_next_responder rightMouseDragged: theEvent]; 299 else 300 [self noResponderFor: @selector(rightMouseDragged:)]; 301} 302 303- (void) rightMouseUp: (NSEvent*)theEvent 304{ 305 if (_next_responder) 306 [_next_responder rightMouseUp: theEvent]; 307 else 308 [self noResponderFor: @selector(rightMouseUp:)]; 309} 310 311- (void) scrollWheel: (NSEvent *)theEvent 312{ 313 if (_next_responder) 314 [_next_responder scrollWheel: theEvent]; 315 else 316 [self noResponderFor: @selector(scrollWheel:)]; 317} 318 319/* 320 * Services menu support 321 */ 322- (id) validRequestorForSendType: (NSString*)typeSent 323 returnType: (NSString*)typeReturned 324{ 325 if (_next_responder) 326 return [_next_responder validRequestorForSendType: typeSent 327 returnType: typeReturned]; 328 else 329 return nil; 330} 331 332/* 333 * NSCoding protocol 334 * NB. Don't encode responder chain - it's transient information that should 335 * be reconstructed from else where in the encoded archive. 336 */ 337- (void) encodeWithCoder: (NSCoder*)aCoder 338{ 339 if ([aCoder allowsKeyedCoding]) 340 { 341 if (_interface_style != NSNoInterfaceStyle) 342 { 343 [aCoder encodeInt: _interface_style 344 forKey: @"NSInterfaceStyle"]; 345 } 346 347 if ([self menu] != nil) 348 { 349 [aCoder encodeObject: [self menu] 350 forKey: @"NSMenu"]; 351 } 352 if ([self nextResponder] != nil) 353 { 354 [aCoder encodeConditionalObject: [self nextResponder] 355 forKey: @"NSNextResponder"]; 356 } 357 } 358 else 359 { 360 [aCoder encodeValueOfObjCType: @encode(int) at: &_interface_style]; 361 [aCoder encodeObject: _menu]; 362 } 363} 364 365- (id) initWithCoder: (NSCoder*)aDecoder 366{ 367 id obj = nil; 368 369 if ([aDecoder allowsKeyedCoding]) 370 { 371 if ([aDecoder containsValueForKey: @"NSInterfaceStyle"]) 372 { 373 _interface_style = [aDecoder decodeIntForKey: @"NSInterfaceStyle"]; 374 } 375 376 if ([aDecoder containsValueForKey: @"NSMenu"]) 377 { 378 obj = [aDecoder decodeObjectForKey: @"NSMenu"]; 379 } 380 381 if ([aDecoder containsValueForKey: @"NSNextResponder"]) 382 { 383 [self setNextResponder: [aDecoder decodeObjectForKey: @"NSNextResponder"]]; 384 } 385 } 386 else 387 { 388 [aDecoder decodeValueOfObjCType: @encode(int) at: &_interface_style]; 389 obj = [aDecoder decodeObject]; 390 } 391 392 [self setMenu: obj]; 393 394 return self; 395} 396- (void) dealloc 397{ 398 RELEASE(_menu); 399 [super dealloc]; 400} 401- (NSMenu*) menu 402{ 403 return _menu; 404} 405 406- (void) setMenu: (NSMenu*)aMenu 407{ 408 ASSIGN(_menu, aMenu); 409} 410 411- (NSInterfaceStyle) interfaceStyle 412{ 413 return _interface_style; 414} 415 416- (void) setInterfaceStyle: (NSInterfaceStyle)aStyle 417{ 418 _interface_style = aStyle; 419} 420 421- (NSUndoManager*) undoManager 422{ 423 if (_next_responder) 424 return [_next_responder undoManager]; 425 else 426 return nil; 427} 428 429- (BOOL) shouldBeTreatedAsInkEvent: (NSEvent *)theEvent 430{ 431 return NO; 432} 433 434- (BOOL)presentError:(NSError *)error 435{ 436 error = [self willPresentError: error]; 437 438 if (_next_responder) 439 { 440 return [_next_responder presentError: error]; 441 } 442 else 443 { 444 return [NSApp presentError: error]; 445 } 446} 447 448- (void)presentError:(NSError *)error 449 modalForWindow:(NSWindow *)window 450 delegate:(id)delegate 451 didPresentSelector:(SEL)sel 452 contextInfo:(void *)context 453{ 454 error = [self willPresentError: error]; 455 if (_next_responder) 456 { 457 [_next_responder presentError: error 458 modalForWindow: window 459 delegate: delegate 460 didPresentSelector: sel 461 contextInfo: context]; 462 } 463 else 464 { 465 [NSApp presentError: error 466 modalForWindow: window 467 delegate: delegate 468 didPresentSelector: sel 469 contextInfo: context]; 470 } 471} 472 473- (NSError *) willPresentError: (NSError *)error 474{ 475 return error; 476} 477 478@end 479