1/** <title>GSNibLoading</title> 2 3 <abstract> 4 These are templates for use with OSX Nib files. These classes are the 5 templates and other things which are needed for reading/writing nib files. 6 </abstract> 7 8 Copyright (C) 1997, 1999 Free Software Foundation, Inc. 9 10 Author: Gregory John Casamento 11 Date: 2003, 2005 12 Author: Fred Kiefer 13 Date: 2003, 2010 14 15 This file is part of the GNUstep GUI Library. 16 17 This library is free software; you can redistribute it and/or 18 modify it under the terms of the GNU Lesser General Public 19 License as published by the Free Software Foundation; either 20 version 2 of the License, or (at your option) any later version. 21 22 This library is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 Lesser General Public License for more details. 26 27 You should have received a copy of the GNU Lesser General Public 28 License along with this library; see the file COPYING.LIB. 29 If not, see <http://www.gnu.org/licenses/> or write to the 30 Free Software Foundation, 51 Franklin Street, Fifth Floor, 31 Boston, MA 02110-1301, USA. 32*/ 33 34#define EXPOSE_NSKeyedUnarchiver_IVARS 35 36#import <Foundation/NSArchiver.h> 37#import <Foundation/NSArray.h> 38#import <Foundation/NSBundle.h> 39#import <Foundation/NSByteOrder.h> 40#import <Foundation/NSCoder.h> 41#import <Foundation/NSData.h> 42#import <Foundation/NSDecimalNumber.h> 43#import <Foundation/NSDictionary.h> 44#import <Foundation/NSDebug.h> 45#import <Foundation/NSEnumerator.h> 46#import <Foundation/NSException.h> 47#import <Foundation/NSKeyedArchiver.h> 48#import <Foundation/NSKeyValueCoding.h> 49#import <Foundation/NSObjCRuntime.h> 50#import <Foundation/NSSet.h> 51#import <Foundation/NSString.h> 52 53#import "GNUstepGUI/GSNibLoading.h" 54#import "AppKit/NSApplication.h" 55#import "AppKit/NSFontManager.h" 56#import "AppKit/NSImage.h" 57#import "AppKit/NSMenuItem.h" 58#import "AppKit/NSMenuView.h" 59#import "AppKit/NSNib.h" 60#import "AppKit/NSScreen.h" 61#import "AppKit/NSSound.h" 62#import "AppKit/NSToolbar.h" 63#import "GNUstepGUI/GSInstantiator.h" 64#import "GSGuiPrivate.h" 65 66static BOOL _isInInterfaceBuilder = NO; 67 68@interface NSKeyedUnarchiver (NSClassSwapperPrivate) 69- (Class) replacementClassForClassName: (NSString *)className; 70@end 71 72@interface NSApplication (NibCompatibility) 73- (void) _setMainMenu: (NSMenu*)aMenu; 74@end 75 76@interface NSView (NibCompatibility) 77- (void) _fixSubviews; 78@end 79 80/* Correct some instances where the ":" is missing from the method name in the label */ 81@interface NSNibControlConnector (NibCompatibility) 82- (void) instantiateWithInstantiator: (id<GSInstantiator>)instantiator; 83@end 84 85@interface NSNibConnector (NibCompatibility) 86- (void) instantiateWithInstantiator: (id<GSInstantiator>)instantiator; 87@end 88 89@interface NSDecimalNumberPlaceholder : NSObject 90@end 91 92@interface _NSCornerView : NSView 93@end 94 95@interface NSMenu (NibCompatibility) 96- (void) _setMain: (BOOL)isMain; 97@end 98@interface NSMenu (GNUstepPrivate) 99- (void) _setGeometry; 100- (BOOL) _isMainMenu; 101@end 102 103@implementation NSMenu (NibCompatibility) 104// FIXME: Why can't this be merged with setMain: ? 105- (void) _setMain: (BOOL)isMain 106{ 107 if (isMain) 108 { 109 NSMenuView *oldRep; 110 NSInterfaceStyle oldStyle; 111 NSInterfaceStyle newStyle; 112 NSString *processName; 113 114 if ([self numberOfItems] == 0) 115 return; 116 117 oldRep = [self menuRepresentation]; 118 oldStyle = [oldRep interfaceStyle]; 119 newStyle = NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil); 120 processName = [[NSProcessInfo processInfo] processName]; 121 122 /* 123 * If necessary, rebuild menu for (different) style 124 */ 125 if (oldStyle != newStyle) 126 { 127 NSMenuView *newRep; 128 129 newRep = [[NSMenuView alloc] initWithFrame: NSZeroRect]; 130 if (newStyle == NSMacintoshInterfaceStyle 131 || newStyle == NSWindows95InterfaceStyle) 132 { 133 [newRep setHorizontal: YES]; 134 } 135 else 136 { 137 [newRep setHorizontal: NO]; 138 } 139 [newRep setInterfaceStyle: newStyle]; 140 [self setMenuRepresentation: newRep]; 141 RELEASE(newRep); 142 } 143 144 [[self window] setTitle: processName]; 145 [[self window] setLevel: NSMainMenuWindowLevel]; 146 147 // if it's a standard menu, transform it to be more NeXT'ish/GNUstep-like 148 if (_menu.horizontal == NO) 149 { 150 NSMenuItem *appItem; 151 NSMenu *sub; 152 SEL sel = @selector(terminate:); 153 154 /* The title of the main menu should be the process name. 155 */ 156 [self setTitle: processName]; 157 158 /* If there is no 'quite' item (one which sends a -terminate: 159 * actions) we add one. 160 */ 161 if ([self indexOfItemWithTarget: nil andAction: sel] < 0 162 && [self indexOfItemWithTarget: NSApp andAction: sel] < 0) 163 { 164 NSString *quitString; 165 NSMenuItem *quitItem; 166 167 quitString = [NSString stringWithFormat: @"%@ %@", 168 NSLocalizedString (@"Quit", @"Quit"), processName]; 169 quitItem = [[NSMenuItem alloc] initWithTitle: quitString 170 action: @selector(terminate:) 171 keyEquivalent: @"q"]; 172 [self addItem: quitItem]; 173 } 174 175 /* An OSX main menu has the first item pointing to a submenu 176 * whose contents are much the same as a GNUstep info menu. 177 */ 178 appItem = (NSMenuItem*)[self itemAtIndex: 0]; // Info item. 179 sub = [appItem submenu]; 180 if (sub != nil) 181 { 182 NSString *infoString; 183 NSInteger index; 184 185 infoString = NSLocalizedString (@"Info", @"Info"); 186 [appItem setTitle: infoString]; 187 [sub setTitle: infoString]; 188 /* The submenu may contain a 'quit' item ... if so we need to 189 * remove it as we already added one to the main menu. 190 */ 191 index = [sub indexOfItemWithTarget: nil andAction: sel]; 192 if (index < 0) 193 { 194 index = [sub indexOfItemWithTarget: NSApp andAction: sel]; 195 } 196 if (index >= 0) 197 { 198 [sub removeItemAtIndex: index]; 199 } 200 } 201 } 202 203 [self _setGeometry]; 204 [self sizeToFit]; 205 206 if ([NSApp isActive]) 207 { 208 [self display]; 209 } 210 } 211 else 212 { 213 [self close]; 214 [[self window] setLevel: NSSubmenuWindowLevel]; 215 } 216} 217@end 218 219@implementation NSApplication (NibCompatibility) 220- (void) _setMainMenu: (NSMenu*)aMenu 221{ 222 if (_main_menu == aMenu) 223 { 224 return; 225 } 226 227 if (_main_menu != nil) 228 { 229 [_main_menu setMain: NO]; 230 } 231 232 ASSIGN(_main_menu, aMenu); 233 234 if (_main_menu != nil) 235 { 236 [_main_menu _setMain: YES]; 237 } 238} 239@end 240 241@implementation NSView (NibCompatibility) 242- (void) _setWindow: (id) w 243{ 244 _window = w; 245} 246 247- (void) _fixSubviews 248{ 249 NSEnumerator *en = [[self subviews] objectEnumerator]; 250 id v = nil; 251 while ((v = [en nextObject]) != nil) 252 { 253 if ([v window] != [self window] || 254 [v superview] != self) 255 { 256 [v _setWindow: [self window]]; 257 RETAIN(v); 258 [_sub_views removeObject: v]; 259 [self addSubview: v]; 260 RELEASE(v); 261 } 262 [v _fixSubviews]; 263 } 264} 265@end 266 267/** 268 * NSWindowTemplate 269 * 270 * Instances of this class take the place of all windows in the nib file. 271 */ 272@implementation NSWindowTemplate 273+ (void) initialize 274{ 275 if (self == [NSWindowTemplate class]) 276 { 277 [self setVersion: 0]; 278 } 279} 280 281- (void) dealloc 282{ 283 RELEASE(_title); 284 RELEASE(_viewClass); 285 RELEASE(_windowClass); 286 RELEASE(_view); 287 RELEASE(_autosaveName); 288 RELEASE(_realObject); 289 [super dealloc]; 290} 291 292/** 293 * Designated initializer for NSWindowTemplate. 294 */ 295- (id) initWithWindow: (NSWindow *)window 296 className: (NSString *)windowClass 297 isDeferred: (BOOL) deferred 298 isOneShot: (BOOL) oneShot 299 isVisible: (BOOL) visible 300 wantsToBeColor: (BOOL) wantsToBeColor 301 autoPositionMask: (int) autoPositionMask 302{ 303 if ((self = [super init]) != nil) 304 { 305 if (window != nil) 306 { 307 // object members 308 ASSIGN(_title, [window title]); 309 ASSIGN(_viewClass, NSStringFromClass([[window contentView] class])); 310 ASSIGN(_windowClass, windowClass); 311 ASSIGN(_view, [window contentView]); 312 ASSIGN(_autosaveName, [window frameAutosaveName]); 313 314 // style & size 315 _windowStyle = [window styleMask]; 316 _backingStoreType = [window backingType]; 317 //_maxSize = [window maxSize]; 318 //_minSize = [window minSize]; 319 _maxSize = [window contentMaxSize]; 320 _minSize = [window contentMinSize]; 321 _windowRect = [window frame]; 322 _screenRect = [[NSScreen mainScreen] frame]; 323 324 // flags 325 _flags.isHiddenOnDeactivate = [window hidesOnDeactivate]; 326 _flags.isNotReleasedOnClose = (![window isReleasedWhenClosed]); 327 _flags.isDeferred = deferred; 328 _flags.isOneShot = oneShot; 329 _flags.isVisible = visible; 330 _flags.isNotShadowed = ![window hasShadow]; 331 _flags.wantsToBeColor = wantsToBeColor; 332 _flags.dynamicDepthLimit = [window hasDynamicDepthLimit]; 333 _flags.autoPositionMask = autoPositionMask; 334 _flags.savePosition = YES; // not yet implemented. 335 _flags.autorecalculatesKeyViewLoop = [window autorecalculatesKeyViewLoop]; 336 } 337 } 338 return self; 339} 340 341- (id) initWithCoder: (NSCoder *)coder 342{ 343 if ([coder allowsKeyedCoding]) 344 { 345 if ([coder containsValueForKey: @"NSViewClass"]) 346 { 347 ASSIGN(_viewClass, [coder decodeObjectForKey: @"NSViewClass"]); 348 } 349 else 350 { 351 ASSIGN(_viewClass, @"NSView"); 352 } 353 if ([coder containsValueForKey: @"NSWindowClass"]) 354 { 355 ASSIGN(_windowClass, [coder decodeObjectForKey: @"NSWindowClass"]); 356 } 357 else 358 { 359 ASSIGN(_windowClass, @"NSWindow"); 360 } 361 if ([coder containsValueForKey: @"NSWindowStyleMask"]) 362 { 363 _windowStyle = [coder decodeIntForKey: @"NSWindowStyleMask"]; 364 } 365 else 366 { 367 _windowStyle = 0; 368 } 369 if ([coder containsValueForKey: @"NSWindowBacking"]) 370 { 371 _backingStoreType = [coder decodeIntForKey: @"NSWindowBacking"]; 372 } 373 if ([coder containsValueForKey: @"NSWindowView"]) 374 { 375 ASSIGN(_view, [coder decodeObjectForKey: @"NSWindowView"]); 376 } 377 if ([coder containsValueForKey: @"NSWTFlags"]) 378 { 379 unsigned long flags = [coder decodeIntForKey: @"NSWTFlags"]; 380 memcpy((void *)&_flags,(void *)&flags,sizeof(struct _GSWindowTemplateFlags)); 381 } 382 383 if ([coder containsValueForKey: @"NSWindowContentMinSize"]) 384 { 385 _minSize = [coder decodeSizeForKey: @"NSWindowContentMinSize"]; 386 } 387 else if ([coder containsValueForKey: @"NSMinSize"]) 388 { 389 NSRect rect = NSZeroRect; 390 rect.size = [coder decodeSizeForKey: @"NSMinSize"]; 391 rect = [NSWindow contentRectForFrameRect: rect 392 styleMask: _windowStyle]; 393 _minSize = rect.size; 394 } 395 396 if ([coder containsValueForKey: @"NSWindowContentMaxSize"]) 397 { 398 _maxSize = [coder decodeSizeForKey: @"NSWindowContentMaxSize"]; 399 } 400 else if ([coder containsValueForKey: @"NSMaxSize"]) 401 { 402 NSRect rect = NSZeroRect; 403 rect.size = [coder decodeSizeForKey: @"NSMaxSize"]; 404 rect = [NSWindow contentRectForFrameRect: rect 405 styleMask: _windowStyle]; 406 _maxSize = rect.size; 407 } 408 else 409 { 410 _maxSize = NSMakeSize (10e4, 10e4); 411 } 412 413 if ([coder containsValueForKey: @"NSWindowRect"]) 414 { 415 _windowRect = [coder decodeRectForKey: @"NSWindowRect"]; 416 } 417 if ([coder containsValueForKey: @"NSFrameAutosaveName"]) 418 { 419 ASSIGN(_autosaveName, [coder decodeObjectForKey: @"NSFrameAutosaveName"]); 420 } 421 if ([coder containsValueForKey: @"NSWindowTitle"]) 422 { 423 ASSIGN(_title, [coder decodeObjectForKey: @"NSWindowTitle"]); 424 _windowStyle |= NSTitledWindowMask; 425 } 426 427 if ([coder containsValueForKey: @"NSToolbar"]) 428 { 429 _toolbar = [coder decodeObjectForKey: @"NSToolbar"]; 430 } 431 432 _baseWindowClass = [NSWindow class]; 433 } 434 else 435 { 436 [NSException raise: NSInvalidArgumentException 437 format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), 438 NSStringFromClass([coder class])]; 439 } 440 return self; 441} 442 443- (void) encodeWithCoder: (NSCoder *)aCoder 444{ 445 if ([aCoder allowsKeyedCoding]) 446 { 447 unsigned long flags = 0; 448 NSRect rect = [NSWindow contentRectForFrameRect: _windowRect 449 styleMask: _windowStyle]; 450 memcpy((void *)&flags,(void *)&_flags,sizeof(unsigned long)); 451 452 [aCoder encodeObject: _viewClass forKey: @"NSViewClass"]; 453 [aCoder encodeObject: _windowClass forKey: @"NSWindowClass"]; 454 [aCoder encodeInt: _windowStyle forKey: @"NSWindowStyleMask"]; 455 [aCoder encodeInt: _backingStoreType forKey: @"NSWindowBacking"]; 456 [aCoder encodeObject: _view forKey: @"NSWindowView"]; 457 [aCoder encodeInt: flags forKey: @"NSWTFlags"]; 458 [aCoder encodeSize: _minSize forKey: @"NSWindowContentMinSize"]; 459 [aCoder encodeSize: _maxSize forKey: @"NSWindowContentMaxSize"]; 460 [aCoder encodeRect: rect forKey: @"NSWindowRect"]; 461 [aCoder encodeObject: _title forKey: @"NSWindowTitle"]; 462 [aCoder encodeObject: _autosaveName forKey: @"NSFrameAutosaveName"]; 463 [aCoder encodeObject: _toolbar forKey: @"NSToolbar"]; 464 } 465} 466 467/** 468 * This method is used to get the real object when connections are established. 469 */ 470- (id) nibInstantiate 471{ 472 if (_realObject == nil) 473 { 474 Class aClass; 475 476 if ([NSClassSwapper isInInterfaceBuilder]) 477 { 478 aClass = [self baseWindowClass]; 479 } 480 else 481 { 482 aClass = NSClassFromString(_windowClass); 483 } 484 485 if (aClass == nil) 486 { 487 [NSException raise: NSInternalInconsistencyException 488 format: @"Unable to find class '%@'", _windowClass]; 489 } 490 491 _realObject = [[aClass allocWithZone: NSDefaultMallocZone()] 492 initWithContentRect: _windowRect 493 styleMask: _windowStyle 494 backing: _backingStoreType 495 defer: _flags.isDeferred]; 496 497 // set flags... 498 [_realObject setHidesOnDeactivate: _flags.isHiddenOnDeactivate]; 499 [_realObject setReleasedWhenClosed: !(_flags.isNotReleasedOnClose)]; 500 [_realObject setOneShot: _flags.isOneShot]; 501 // [_realObject setVisible: _flags.isVisible]; // this is determined by whether it's in the visible windows array... 502 // [_realObject setWantsToBeColor: _flags.wantsToBeColor]; // not applicable on GNUstep. 503 [_realObject setAutodisplay: YES]; 504 [_realObject setDynamicDepthLimit: _flags.dynamicDepthLimit]; 505 // [_realObject setAutoPositionMask: _flags.autoPositionMask]; // currently not implemented for nibs 506 // [_realObject setAutoPosition: _flags.autoPosition]; 507 [_realObject setDynamicDepthLimit: _flags.dynamicDepthLimit]; 508 // [_realObject setFrameAutosaveName: _autosaveName]; // done after setting the min/max sizes 509 [_realObject setHasShadow: !_flags.isNotShadowed]; 510 [_realObject setAutorecalculatesKeyViewLoop: _flags.autorecalculatesKeyViewLoop]; 511 512 // reset attributes... 513 [_realObject setContentView: _view]; 514 //[_realObject setMinSize: _minSize]; 515 //[_realObject setMaxSize: _maxSize]; 516 [_realObject setTitle: _title]; 517 518 if ([_viewClass isKindOfClass: [NSToolbar class]]) 519 { 520 // FIXME: No idea what is going on here 521 [_realObject setToolbar: (NSToolbar*)_viewClass]; 522 } 523 if (_toolbar) 524 { 525 [_realObject setToolbar: _toolbar]; 526 } 527 528 [_realObject setContentMinSize: _minSize]; 529 [_realObject setContentMaxSize: _maxSize]; 530 531 [_view _fixSubviews]; 532 533 // FIXME What is the point of calling -setFrame:display: here? It looks 534 // like an effective no op to me. 535 // resize the window... 536 [_realObject setFrame: [NSWindow frameRectForContentRect: [self windowRect] 537 styleMask: [self windowStyle]] 538 display: NO]; 539 [_realObject setFrameAutosaveName: _autosaveName]; 540 } 541 return _realObject; 542} 543 544// setters and getters 545/** 546 * sets the type of backing store the window uses. 547 */ 548- (void) setBackingStoreType: (NSBackingStoreType)type 549{ 550 _backingStoreType = type; 551} 552 553/** 554 * Returns the type of backing store which is used. 555 */ 556- (NSBackingStoreType) backingStoreType 557{ 558 return _backingStoreType; 559} 560 561/** 562 * Sets whether or not the window is deferred. 563 */ 564- (void) setDeferred: (BOOL)flag 565{ 566 _flags.isDeferred = flag; 567} 568 569/** 570 * Returns YES, if the window is deferred, NO otherwise. 571 */ 572- (BOOL) isDeferred 573{ 574 return _flags.isDeferred; 575} 576 577/** 578 * Sets the maximum size of the window. 579 */ 580- (void) setMaxSize: (NSSize)maxSize 581{ 582 _maxSize = maxSize; 583} 584 585/** 586 * Returns the maximum size of the window. 587 */ 588- (NSSize) maxSize 589{ 590 return _maxSize; 591} 592 593/** 594 * Sets the minimum size of the window. 595 */ 596- (void) setMinSize: (NSSize)minSize 597{ 598 _minSize = minSize; 599} 600 601/** 602 * Returns the maximum size of the window. 603 */ 604- (NSSize) minSize 605{ 606 return _minSize; 607} 608 609/** 610 * Sets the window style. 611 */ 612- (void) setWindowStyle: (unsigned)style 613{ 614 _windowStyle = style; 615} 616 617/** 618 * Returns the window style. 619 */ 620- (unsigned) windowStyle 621{ 622 return _windowStyle; 623} 624 625/** 626 * Sets the window title. 627 */ 628- (void) setTitle: (NSString *) title 629{ 630 ASSIGN(_title, title); 631} 632 633/** 634 * Returns the window style. 635 */ 636- (NSString *)title; 637{ 638 return _title; 639} 640 641/** 642 * Sets the class used for the content view. 643 */ 644- (void) setViewClass: (NSString *)viewClass 645{ 646 ASSIGN(_viewClass,viewClass); 647} 648 649/** 650 * Returns the name of the class used for the content view. 651 */ 652- (NSString *)viewClass 653{ 654 return _viewClass; 655} 656 657/** 658 * Sets the window rect. 659 */ 660- (void) setWindowRect: (NSRect)rect 661{ 662 _windowRect = rect; 663} 664 665/** 666 * Returns the window rect. 667 */ 668- (NSRect)windowRect 669{ 670 return _windowRect; 671} 672 673/** 674 * Sets the screen rect. 675 */ 676- (void) setScreenRect: (NSRect)rect 677{ 678 _screenRect = rect; 679} 680 681/** 682 * Returns the screen rect. 683 */ 684- (NSRect) screenRect 685{ 686 return _screenRect; 687} 688 689/** 690 * Sets the instantiated object/real object. 691 */ 692- (void) setRealObject: (id)o 693{ 694 ASSIGN(_realObject,o); 695} 696 697/** 698 * Returns the real object represented by this template. 699 */ 700- (id) realObject 701{ 702 return _realObject; 703} 704 705/** 706 * Sets the view instance. 707 */ 708- (void) setView: (id)view 709{ 710 ASSIGN(_view,view); 711} 712 713/** 714 * Gets the view instance. 715 */ 716- (id) view 717{ 718 return _view; 719} 720 721/** 722 * sets the class name to be used when unarchiving the window. 723 */ 724- (void) setClassName: (NSString *)name 725{ 726 ASSIGN(_windowClass, name); 727} 728 729/** 730 * Returns the class instance. 731 */ 732- (NSString *)className 733{ 734 return _windowClass; 735} 736 737/** 738 * Returns the base window class. This is usually NSWindow, but this method 739 * is overriden in the editor so that a different class may be used to take the 740 * place of the window. In the case of Gorm, this is GormNSWindow. 741 */ 742- (Class) baseWindowClass 743{ 744 return _baseWindowClass; 745} 746@end 747 748/* 749 * NSViewTemplate 750 * 751 * Template for any classes which derive from NSView 752 */ 753@implementation NSViewTemplate 754+ (void) initialize 755{ 756 if (self == [NSViewTemplate class]) 757 { 758 [self setVersion: 0]; 759 } 760} 761 762- (void) dealloc 763{ 764 RELEASE(_className); 765 RELEASE(_realObject); 766 [super dealloc]; 767} 768 769/** 770 * Designated initializer for NSViewTemplate. 771 */ 772- (id) initWithObject: (id)o 773 className: (NSString *)name 774{ 775 if ((self = [super init]) != nil) 776 { 777 [self setRealObject: o]; 778 [self setClassName: name]; 779 } 780 return self; 781} 782 783- (id) initWithCoder: (NSCoder *)coder 784{ 785 self = [super initWithCoder: coder]; 786 if (self != nil) 787 { 788 if ([coder allowsKeyedCoding]) 789 { 790 _className = [coder decodeObjectForKey: @"NSClassName"]; 791 } 792 793 if (_realObject == nil) 794 { 795 Class aClass = NSClassFromString(_className); 796 if (aClass == nil) 797 { 798 [NSException raise: NSInternalInconsistencyException 799 format: @"Unable to find class '%@'", _className]; 800 } 801 else 802 { 803 ASSIGN(_realObject, [[aClass allocWithZone: NSDefaultMallocZone()] initWithCoder: coder]); 804 [[self superview] replaceSubview: self with: _realObject]; // replace the old view... 805 } 806 } 807 808 AUTORELEASE(self); 809 return _realObject; 810 } 811 else 812 { 813 [NSException raise: NSInvalidArgumentException 814 format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), 815 NSStringFromClass([coder class])]; 816 } 817 return nil; 818} 819 820- (void) encodeWithCoder: (NSCoder *)coder 821{ 822 if ([coder allowsKeyedCoding]) 823 { 824 [coder encodeObject: (id)_className forKey: @"NSClassName"]; 825 [_realObject encodeWithCoder: coder]; 826 } 827 else 828 { 829 [NSException raise: NSInvalidArgumentException 830 format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), 831 NSStringFromClass([coder class])]; 832 } 833} 834 835// setters and getters 836/** 837 * Set the class name to be used by the NSView subclass. 838 */ 839- (void) setClassName: (NSString *)name 840{ 841 ASSIGN(_className, name); 842} 843 844/** 845 * Returns the classname. 846 */ 847- (NSString *)className 848{ 849 return _className; 850} 851 852/** 853 * Set the real object of the template. 854 */ 855- (void) setRealObject: (id)o 856{ 857 ASSIGN(_realObject, o); 858} 859 860/** 861 * Get the real object represented by the template. 862 */ 863- (id) realObject 864{ 865 return _realObject; 866} 867@end 868 869// Template for any classes which derive from NSText 870@implementation NSTextTemplate 871+ (void) initialize 872{ 873 if (self == [NSTextTemplate class]) 874 { 875 [self setVersion: 0]; 876 } 877} 878@end 879 880/** 881 * NSTextViewTemplate 882 * 883 * Template for any classes which derive from NSTextView 884 */ 885@implementation NSTextViewTemplate 886+ (void) initialize 887{ 888 if (self == [NSTextViewTemplate class]) 889 { 890 [self setVersion: 0]; 891 } 892} 893@end 894 895// Template for any classes which derive from NSMenu. 896@implementation NSMenuTemplate 897+ (void) initialize 898{ 899 if (self == [NSMenuTemplate class]) 900 { 901 [self setVersion: 0]; 902 } 903} 904 905- (void) dealloc 906{ 907 RELEASE(_menuClass); 908 RELEASE(_realObject); 909 [super dealloc]; 910} 911 912- (id) initWithCoder: (NSCoder *)aCoder 913{ 914 RELEASE(self); 915 return nil; 916} 917 918- (void) encodeWithCoder: (NSCoder *)aCoder 919{ 920} 921 922- (void) setClassName: (NSString *)className 923{ 924 ASSIGN(_menuClass, className); 925} 926 927- (NSString *)className 928{ 929 return _menuClass; 930} 931 932- (void) setRealObject: (id)o 933{ 934 ASSIGN(_realObject,o); 935} 936 937- (id) realObject 938{ 939 return _realObject; 940} 941@end 942 943@implementation NSCustomObject 944- (void) setClassName: (NSString *)name 945{ 946 ASSIGNCOPY(_className, name); 947} 948 949- (NSString *)className 950{ 951 return _className; 952} 953 954- (void) setExtension: (NSString *)name 955{ 956 ASSIGNCOPY(_extension, name); 957} 958 959- (NSString *)extension 960{ 961 return _extension; 962} 963 964- (void) setRealObject: (id)obj 965{ 966 ASSIGN(_object, obj); 967} 968 969- (id) realObject 970{ 971 return _object; 972} 973 974- (id) initWithCoder: (NSCoder *)coder 975{ 976 if ([coder allowsKeyedCoding]) 977 { 978 ASSIGN(_className, [coder decodeObjectForKey: @"NSClassName"]); 979 ASSIGN(_extension, [coder decodeObjectForKey: @"NSExtension"]); 980 ASSIGN(_object, [coder decodeObjectForKey: @"NSObject"]); 981 } 982 else 983 { 984 [NSException raise: NSInvalidArgumentException 985 format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), 986 NSStringFromClass([coder class])]; 987 } 988 return self; 989} 990 991- (void) encodeWithCoder: (NSCoder *)coder 992{ 993 if ([coder allowsKeyedCoding]) 994 { 995 [coder encodeObject: (id)_className forKey: @"NSClassName"]; 996 [coder encodeConditionalObject: (id)_extension forKey: @"NSExtension"]; 997 [coder encodeConditionalObject: (id)_object forKey: @"NSObject"]; 998 } 999 else 1000 { 1001 [NSException raise: NSInvalidArgumentException 1002 format: @"Keyed coding not implemented for %@.", 1003 NSStringFromClass([self class])]; 1004 } 1005 1006} 1007 1008- (id) nibInstantiate 1009{ 1010 if (_object == nil) 1011 { 1012 Class aClass; 1013 1014 if ([NSClassSwapper isInInterfaceBuilder]) 1015 { 1016 aClass = [self class]; 1017 } 1018 else 1019 { 1020 aClass = NSClassFromString(_className); 1021 } 1022 1023 if (aClass == nil) 1024 { 1025 [NSException raise: NSInternalInconsistencyException 1026 format: @"Unable to find class '%@'", _className]; 1027 } 1028 1029 if (GSObjCIsKindOf(aClass, [NSApplication class]) || 1030 [_className isEqual: @"NSApplication"]) 1031 { 1032 _object = RETAIN([aClass sharedApplication]); 1033 } 1034 else if ((GSObjCIsKindOf(aClass, [NSFontManager class])) || 1035 ([_className isEqual: @"NSFontManager"])) 1036 { 1037 _object = RETAIN([aClass sharedFontManager]); 1038 } 1039 else 1040 { 1041 _object = [[aClass allocWithZone: NSDefaultMallocZone()] init]; 1042 } 1043 } 1044 return _object; 1045} 1046 1047- (void) awakeFromNib 1048{ 1049 NSDebugLog(@"Called awakeFromNib on an NSCustomObject instance: %@", self); 1050 if ([_object respondsToSelector: @selector(awakeFromNib)]) 1051 { 1052 [_object awakeFromNib]; 1053 } 1054} 1055 1056- (NSString *) description 1057{ 1058 return [NSString stringWithFormat: @"<%s: %lx> = <<className: %@, object: %@>>", 1059 GSClassNameFromObject(self), 1060 (unsigned long)self, 1061 _className,_object]; 1062} 1063 1064- (void) dealloc 1065{ 1066 RELEASE(_className); 1067 RELEASE(_extension); 1068 RELEASE(_object); 1069 [super dealloc]; 1070} 1071@end 1072 1073@implementation NSCustomView 1074- (void) setClassName: (NSString *)name 1075{ 1076 ASSIGNCOPY(_className, name); 1077} 1078 1079- (NSString *)className 1080{ 1081 return _className; 1082} 1083- (void) setExtension: (NSString *)ext; 1084{ 1085 ASSIGNCOPY(_extension, ext); 1086} 1087 1088- (NSString *)extension 1089{ 1090 return _extension; 1091} 1092 1093- (id) nibInstantiate 1094{ 1095 if ([NSClassSwapper isInInterfaceBuilder]) 1096 { 1097 _view = self; 1098 return self; 1099 } 1100 1101 if (_view == nil) 1102 { 1103 Class aClass; 1104 1105 // If the class name is nil, assume NSView. 1106 if (_className == nil) 1107 { 1108 aClass = [NSView class]; 1109 } 1110 else 1111 { 1112 aClass = NSClassFromString(_className); 1113 } 1114 1115 if (aClass == nil) 1116 { 1117 [NSException raise: NSInternalInconsistencyException 1118 format: @"Unable to find class '%@'", _className]; 1119 } 1120 else 1121 { 1122 _view = [[aClass allocWithZone: NSDefaultMallocZone()] initWithFrame: [self frame]]; 1123 } 1124 } 1125 1126 return _view; 1127} 1128 1129- (id) nibInstantiateWithCoder: (NSCoder *)coder 1130{ 1131 if ([NSClassSwapper isInInterfaceBuilder]) 1132 { 1133 return _view; 1134 } 1135 else if ([coder allowsKeyedCoding]) 1136 { 1137 NSArray *subs = nil; 1138 id nextKeyView = nil; 1139 id prevKeyView = nil; 1140 NSEnumerator *en = nil; 1141 id v = nil; 1142 1143 // Tell the decoder that the object gets replaced before decoding subviews 1144 [(NSKeyedUnarchiver *)coder replaceObject: self withObject: _view]; 1145 1146 prevKeyView = [coder decodeObjectForKey: @"NSPreviousKeyView"]; 1147 nextKeyView = [coder decodeObjectForKey: @"NSNextKeyView"]; 1148 if (nextKeyView != nil) 1149 { 1150 [_view setNextKeyView: nextKeyView]; 1151 } 1152 if (prevKeyView != nil) 1153 { 1154 [_view setPreviousKeyView: prevKeyView]; 1155 } 1156 if ([coder containsValueForKey: @"NSvFlags"]) 1157 { 1158 int vFlags = [coder decodeIntForKey: @"NSvFlags"]; 1159 [_view setAutoresizingMask: vFlags & 0x3F]; 1160 [_view setAutoresizesSubviews: ((vFlags & 0x100) == 0x100)]; 1161 [_view setHidden: ((vFlags & 0x80000000) == 0x80000000)]; 1162 } 1163 /* 1164 if ([coder containsValueForKey: @"NSNextResponder"]) 1165 { 1166 [_view setNextResponder: [coder decodeObjectForKey: @"NSNextResponder"]]; 1167 } 1168 */ 1169 1170 // reset the bounds... 1171 // [_view setBounds: [_view frame]]; 1172 1173 subs = [coder decodeObjectForKey: @"NSSubviews"]; 1174 en = [subs objectEnumerator]; 1175 while((v = [en nextObject]) != nil) 1176 { 1177 [_view addSubview: v]; 1178 } 1179 } 1180 else 1181 { 1182 [NSException raise: NSInternalInconsistencyException 1183 format: @"Called NSCustomView awakeAfterUsingCoder with non-keyed archiver."]; 1184 } 1185 1186 return _view; 1187} 1188 1189- (id) initWithCoder: (NSCoder *)coder 1190{ 1191 // if in interface builder, then initialize as normal. 1192 if ([NSClassSwapper isInInterfaceBuilder]) 1193 { 1194 self = [super initWithCoder: coder]; 1195 if (self == nil) 1196 { 1197 return nil; 1198 } 1199 } 1200 1201 if ([coder allowsKeyedCoding]) 1202 { 1203 // get the super stuff without calling super... 1204 if ([coder containsValueForKey: @"NSFrame"]) 1205 { 1206 _frame = [coder decodeRectForKey: @"NSFrame"]; 1207 } 1208 else 1209 { 1210 _frame = NSZeroRect; 1211 if ([coder containsValueForKey: @"NSFrameSize"]) 1212 { 1213 _frame.size = [coder decodeSizeForKey: @"NSFrameSize"]; 1214 } 1215 } 1216 1217 ASSIGN(_className, [coder decodeObjectForKey: @"NSClassName"]); 1218 ASSIGN(_extension, [coder decodeObjectForKey: @"NSExtension"]); 1219 1220 if ([self nibInstantiate] != nil) 1221 { 1222 [self nibInstantiateWithCoder: coder]; 1223 } 1224 1225 if (self != _view) 1226 { 1227 AUTORELEASE(self); 1228 } 1229 } 1230 else 1231 { 1232 [NSException raise: NSInvalidArgumentException 1233 format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), 1234 NSStringFromClass([coder class])]; 1235 } 1236 1237 return (id)_view; 1238} 1239 1240- (void) encodeWithCoder: (NSCoder *)coder 1241{ 1242 [super encodeWithCoder: coder]; 1243 if ([coder allowsKeyedCoding]) 1244 { 1245 [coder encodeObject: _className forKey: @"NSClassName"]; 1246 [coder encodeObject: _extension forKey: @"NSExtension"]; 1247 } 1248 else 1249 { 1250 [NSException raise: NSInvalidArgumentException 1251 format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), 1252 NSStringFromClass([coder class])]; 1253 } 1254} 1255@end 1256 1257/** 1258 * This class represents an image or a sound which is referenced by the nib file. 1259 */ 1260@implementation NSCustomResource 1261- (void) setClassName: (NSString *)className 1262{ 1263 ASSIGNCOPY(_className, className); 1264} 1265 1266- (NSString *)className 1267{ 1268 return _className; 1269} 1270 1271- (void) setResourceName: (NSString *)resourceName 1272{ 1273 ASSIGNCOPY(_resourceName, resourceName); 1274} 1275 1276- (NSString *)resourceName 1277{ 1278 return _resourceName; 1279} 1280 1281- (id) initWithCoder: (NSCoder *)coder 1282{ 1283 id realObject = nil; 1284 if ([coder allowsKeyedCoding]) 1285 { 1286 ASSIGN(_className, [coder decodeObjectForKey: @"NSClassName"]); 1287 ASSIGN(_resourceName, [coder decodeObjectForKey: @"NSResourceName"]); 1288 1289 // FIXME: this is a hack, but for now it should do. 1290 if ([_className isEqual: @"NSSound"]) 1291 { 1292 realObject = RETAIN([NSSound soundNamed: _resourceName]); 1293 } 1294 else if ([_className isEqual: @"NSImage"]) 1295 { 1296 realObject = RETAIN([NSImage imageNamed: _resourceName]); 1297 } 1298 1299 if (realObject == nil) 1300 { 1301 NSLog(@"Could not load NSCustomResource %@ for class %@", _resourceName, _className); 1302 // Use a default instead of the missing object 1303 if ([_className isEqual: @"NSSound"]) 1304 { 1305 realObject = RETAIN([NSSound soundNamed: @"Ping"]); 1306 } 1307 else if ([_className isEqual: @"NSImage"]) 1308 { 1309 realObject = RETAIN([NSImage imageNamed: @"GNUstep"]); 1310 } 1311 } 1312 // The object has been substituted, release the placeholder. 1313 RELEASE(self); 1314 } 1315 else 1316 { 1317 [NSException raise: NSInvalidArgumentException 1318 format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), 1319 NSStringFromClass([coder class])]; 1320 } 1321 1322 return realObject; 1323} 1324 1325- (void) encodeWithCoder: (NSCoder *)coder 1326{ 1327 if ([coder allowsKeyedCoding]) 1328 { 1329 [coder encodeObject: (id)_className forKey: @"NSClassName"]; 1330 [coder encodeObject: (id)_resourceName forKey: @"NSResourceName"]; 1331 } 1332} 1333@end 1334 1335/** 1336 * Category to add methods to NSKeyedUnarchiver which are needed during 1337 * nib reading. 1338 */ 1339@implementation NSKeyedUnarchiver (NSClassSwapperPrivate) 1340/** 1341 * This method returns the class which replaces the class named 1342 * by className. It uses the classes map to do this. 1343 */ 1344- (Class) replacementClassForClassName: (NSString *)className 1345{ 1346 Class aClass; 1347 if ((aClass = [self classForClassName: className]) == nil) 1348 { 1349 if ((aClass = [[self class] classForClassName: className]) == nil) 1350 { 1351 aClass = NSClassFromString(className); 1352 if (aClass == nil) 1353 { 1354 [NSException raise: NSInternalInconsistencyException 1355 format: @"NSClassSwapper unable to find class '%@'", className]; 1356 } 1357 } 1358 } 1359 return aClass; 1360} 1361@end 1362 1363/** 1364 * NSClassSwapper 1365 * 1366 * This class is used to stand-in for objects which need to be replaced by another object. 1367 * When this class is loaded in the live application, it unarchives and immediately replaces 1368 * itself with the instance of the object requested. This is necessary since IB/Gorm does 1369 * have objects this is used for in palettes, so there is no "live" or actual instance saved 1370 * in the gorm file... only this object as a stand in. 1371 */ 1372@implementation NSClassSwapper 1373- (id) initWithObject: (id)object 1374 withClassName: (NSString *)className 1375 originalClassName: (NSString *)origClassName 1376{ 1377 if ((self = [super init]) != nil) 1378 { 1379 [self setTemplate: object]; 1380 [self setClassName: className]; 1381 [self setOriginalClassName: origClassName]; 1382 } 1383 return self; 1384} 1385 1386/** 1387 * This class method keeps track of whether or not we are operating within IB/Gorm. 1388 * When unarchiving in IB/Gorm some behavior may need to be surpressed for some objects 1389 * or it 1390 */ 1391+ (void) setIsInInterfaceBuilder: (BOOL)flag 1392{ 1393 _isInInterfaceBuilder = flag; 1394} 1395 1396/** 1397 * returns YES, if we are currently in IB/Gorm. 1398 */ 1399+ (BOOL) isInInterfaceBuilder 1400{ 1401 return _isInInterfaceBuilder; 1402} 1403 1404/** 1405 * Sets the template represented by temp. 1406 */ 1407- (void) setTemplate: (id)temp 1408{ 1409 ASSIGN(_template, temp); 1410} 1411 1412/** 1413 * Returns the template. 1414 */ 1415- (id) template 1416{ 1417 return _template; 1418} 1419 1420/** 1421 * Sets the class name. 1422 */ 1423- (void) setClassName: (NSString *)className 1424{ 1425 ASSIGNCOPY(_className, className); 1426} 1427 1428/** 1429 * Returns the class name. 1430 */ 1431- (NSString *)className 1432{ 1433 return _className; 1434} 1435 1436/** 1437 * Sets the original class name. 1438 */ 1439- (void) setOriginalClassName: (NSString *)className 1440{ 1441 ASSIGNCOPY(_originalClassName, className); 1442} 1443 1444/** 1445 * Returns the original class name. 1446 */ 1447- (NSString *)originalClassName 1448{ 1449 return _originalClassName; 1450} 1451 1452/** 1453 * Instantiates the real object using className. 1454 */ 1455- (void) instantiateRealObject: (NSCoder *)coder withClassName: (NSString *)className 1456{ 1457 Class newClass = nil; 1458 id object = nil; 1459 NSKeyedUnarchiver *decoder = (NSKeyedUnarchiver *)coder; 1460 1461 if ([NSClassSwapper isInInterfaceBuilder] == YES) 1462 { 1463 newClass = [decoder replacementClassForClassName: _originalClassName]; 1464 } 1465 else 1466 { 1467 newClass = [decoder replacementClassForClassName: className]; 1468 } 1469 1470 // swap the class... 1471 object = [newClass allocWithZone: NSDefaultMallocZone()]; 1472 [decoder setDelegate: self]; // set the delegate... 1473 [decoder replaceObject: self withObject: object]; 1474 [self setTemplate: [object initWithCoder: decoder]]; 1475 if (object != _template) 1476 { 1477 [decoder replaceObject: object withObject: _template]; 1478 } 1479 [decoder setDelegate: nil]; // unset the delegate... 1480} 1481 1482/** 1483 * This delegate method makes the proper substitution for cellClass 1484 * when the object needs to have it's own cell. An example of this 1485 * is NSSecureTextField/NSSecureTextFieldCell. 1486 */ 1487- (id) unarchiver: (NSKeyedUnarchiver *)coder 1488 didDecodeObject: (id)obj 1489{ 1490 Class newClass = nil; 1491 id result = obj; 1492 1493 // if we are in an interface builder, then return the original object. 1494 if ([NSClassSwapper isInInterfaceBuilder] == YES) 1495 { 1496 newClass = [coder replacementClassForClassName: _originalClassName]; 1497 } 1498 else 1499 { 1500 newClass = [coder replacementClassForClassName: _className]; 1501 } 1502 1503 // if this is a class which uses cells, override with the new cellClass, if the 1504 // subclass responds to cellClass. 1505 if ([obj isKindOfClass: [NSCell class]] && 1506 [newClass respondsToSelector: @selector(cellClass)] && 1507 [_className isEqualToString: _originalClassName] == NO) 1508 { 1509 Class newCellClass = [newClass cellClass]; 1510 if (newCellClass != [NSCell class]) 1511 { 1512 RELEASE(obj); 1513 result = [[newCellClass alloc] initWithCoder: coder]; 1514 } 1515 } 1516 1517 return result; 1518} 1519 1520/** 1521 * Decode NSClassSwapper. 1522 */ 1523- (id) initWithCoder: (NSCoder *)coder 1524{ 1525 if ([coder allowsKeyedCoding]) 1526 { 1527 ASSIGN(_className, [coder decodeObjectForKey: @"NSClassName"]); 1528 ASSIGN(_originalClassName, [coder decodeObjectForKey: @"NSOriginalClassName"]); 1529 1530 // build the real object... 1531 if ([NSClassSwapper isInInterfaceBuilder] == YES) 1532 { 1533 [self instantiateRealObject: coder withClassName: _originalClassName]; 1534 } 1535 else 1536 { 1537 [self instantiateRealObject: coder withClassName: _className]; 1538 } 1539 1540 { 1541 id object; 1542 1543 object = RETAIN(_template); 1544 RELEASE(self); 1545 return AUTORELEASE(object); 1546 } 1547 } 1548 else 1549 { 1550 [NSException raise: NSInvalidArgumentException 1551 format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), 1552 NSStringFromClass([coder class])]; 1553 } 1554 1555 return self; 1556} 1557 1558/** 1559 * Encode NSClassSwapper. 1560 */ 1561- (void) encodeWithCoder: (NSCoder *)coder 1562{ 1563 if ([coder allowsKeyedCoding]) 1564 { 1565 [coder encodeObject: _originalClassName forKey: @"NSOriginalClassName"]; 1566 [coder encodeObject: _className forKey: @"NSClassName"]; 1567 [_template encodeWithCoder: coder]; // encode the actual object; 1568 } 1569 else 1570 { 1571 [NSException raise: NSInvalidArgumentException 1572 format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), 1573 NSStringFromClass([coder class])]; 1574 } 1575} 1576 1577/** 1578 * Deallocate NSClassSwapper instance. 1579 */ 1580- (void) dealloc 1581{ 1582 RELEASE(_className); 1583 RELEASE(_originalClassName); 1584 RELEASE(_template); 1585 [super dealloc]; 1586} 1587@end 1588 1589@implementation NSNibConnector (NibCompatibility) 1590/** 1591 * This method causes the connection to instantiate the objects in it's source 1592 * and destination. The instantiator is the object which holds any custom 1593 * class information which might be needed to do the proprer substitution of 1594 * objects based on the contents of the maps. 1595 */ 1596- (void) instantiateWithInstantiator: (id<GSInstantiator>)instantiator 1597{ 1598 [self setSource: [instantiator instantiateObject: _src]]; 1599 [self setDestination: [instantiator instantiateObject: _dst]]; 1600} 1601 1602- (id) nibInstantiate 1603{ 1604 if ([_src respondsToSelector: @selector(nibInstantiate)]) 1605 { 1606 [self setSource: [_src nibInstantiate]]; 1607 } 1608 if ([_dst respondsToSelector: @selector(nibInstantiate)]) 1609 { 1610 [self setDestination: [_dst nibInstantiate]]; 1611 } 1612 return self; 1613} 1614 1615@end 1616 1617@implementation NSNibControlConnector (NibCompatibility) 1618/** 1619 * This method overrides the default implementation of instantiate with 1620 * instantiator. It also corrects a common issue in some nib files 1621 * by adding a colon to the end if none was given. It then calls the 1622 * superclass with the corrected label. 1623 */ 1624- (void) instantiateWithInstantiator: (id<GSInstantiator>)instantiator 1625{ 1626 NSRange colonRange = [_tag rangeOfString: @":"]; 1627 NSUInteger location = colonRange.location; 1628 1629 if (location == NSNotFound) 1630 { 1631 NSString *newTag = [NSString stringWithFormat: @"%@:",_tag]; 1632 [self setLabel: (id)newTag]; 1633 } 1634 1635 [super instantiateWithInstantiator: instantiator]; 1636} 1637@end 1638 1639/** 1640 * NSIBObjectData 1641 * 1642 * This class is the container for all of the nib data. It contains several maps. 1643 * The maps are the following: 1644 * 1645 * name -> object (name table) 1646 * object -> name (name table reverse lookup) 1647 * classes -> object (for custom class storage) 1648 * oids -> object (for relating the oid to each object) 1649 * accessibilityOids -> object 1650 * 1651 * The maps are stored in the nib itself as a set of synchronized 1652 * arrays one array containing the keys and the other the values. This is why, in the 1653 * initWithCoder: and encodeWithCoder: methods they are saved as arrays and then 1654 * loaded into NSMapTables. 1655 */ 1656@implementation NSIBObjectData 1657/** 1658 * Get the values from the map in the same order as the keys. 1659 */ 1660- (NSArray *) _valuesForKeys: (NSArray *)keys inMap: (NSMapTable *)map 1661{ 1662 NSMutableArray *result = [NSMutableArray array]; 1663 NSEnumerator *en = [keys objectEnumerator]; 1664 id key = nil; 1665 while ((key = [en nextObject]) != nil) 1666 { 1667 id value = (id)NSMapGet(map,key); 1668 [result addObject: value]; 1669 } 1670 return result; 1671} 1672 1673/** 1674 * Build a map with two arrays of keys and values. 1675 */ 1676- (void) _buildMap: (NSMapTable *)mapTable 1677 withKeys: (NSArray *)keys 1678 andValues: (NSArray *)values 1679{ 1680 NSEnumerator *ken = [keys objectEnumerator]; 1681 NSEnumerator *ven = [values objectEnumerator]; 1682 id key = nil; 1683 id value = nil; 1684 1685 while ((key = [ken nextObject]) != nil && (value = [ven nextObject]) != nil) 1686 { 1687 NSMapInsert(mapTable, key, value); 1688 if (value == nil) 1689 { 1690 NSLog(@"==> WARNING: Value for key %@ is %@",key , value); 1691 } 1692 } 1693} 1694 1695/** 1696 * Encode the NSIBObjectData container 1697 */ 1698- (void) encodeWithCoder: (NSCoder *)coder 1699{ 1700 if ([coder allowsKeyedCoding]) 1701 { 1702 NSArray *accessibilityOidsKeys = (NSArray *)NSAllMapTableKeys(_accessibilityOids); 1703 NSArray *accessibilityOidsValues = [self _valuesForKeys: accessibilityOidsKeys inMap: _accessibilityOids]; 1704 NSArray *classKeys = (NSArray *)NSAllMapTableKeys(_classes); 1705 NSArray *classValues = [self _valuesForKeys: classKeys inMap: _classes]; 1706 NSArray *nameKeys = (NSArray *)NSAllMapTableKeys(_names); 1707 NSArray *nameValues = [self _valuesForKeys: nameKeys inMap: _names]; 1708 NSArray *objectsKeys = (NSArray *)NSAllMapTableKeys(_objects); 1709 NSArray *objectsValues = [self _valuesForKeys: objectsKeys inMap: _objects]; 1710 NSArray *oidsKeys = (NSArray *)NSAllMapTableKeys(_oids); 1711 NSArray *oidsValues = [self _valuesForKeys: oidsKeys inMap: _oids]; 1712 1713 [(NSKeyedArchiver *)coder setClassName: @"_NSCornerView" forClass: NSClassFromString(@"GSTableCornerView")]; 1714 1715 [coder encodeObject: (id)_accessibilityConnectors forKey: @"NSAccessibilityConnectors"]; 1716 [coder encodeObject: (id) accessibilityOidsKeys forKey: @"NSAccessibilityOidsKeys"]; 1717 [coder encodeObject: (id) accessibilityOidsValues forKey: @"NSAccessibilityOidsValues"]; 1718 [coder encodeObject: (id) classKeys forKey: @"NSClassesKeys"]; 1719 [coder encodeObject: (id) classValues forKey: @"NSClassesValues"]; 1720 [coder encodeObject: (id) nameKeys forKey: @"NSNamesKeys"]; 1721 [coder encodeObject: (id) nameValues forKey: @"NSNamesValues"]; 1722 [coder encodeObject: (id) objectsKeys forKey: @"NSObjectsKeys"]; 1723 [coder encodeObject: (id) objectsValues forKey: @"NSObjectsValues"]; 1724 [coder encodeObject: (id) oidsKeys forKey: @"NSOidsKeys"]; 1725 [coder encodeObject: (id) oidsValues forKey: @"NSOidsValues"]; 1726 [coder encodeObject: (id) _connections forKey: @"NSConnections"]; 1727 [coder encodeObject: (id) _fontManager forKey: @"NSFontManager"]; 1728 [coder encodeObject: (id) _framework forKey: @"NSFramework"]; 1729 [coder encodeObject: (id) _visibleWindows forKey: @"NSVisibleWindows"]; 1730 [coder encodeInt: _nextOid forKey: @"NSNextOid"]; 1731 [coder encodeConditionalObject: (id) _root forKey: @"NSRoot"]; 1732 } 1733 else 1734 { 1735 [NSException raise: NSInvalidArgumentException 1736 format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), 1737 NSStringFromClass([coder class])]; 1738 } 1739} 1740 1741/** 1742 * Decode the NSIBObjectData container. 1743 */ 1744- (id) initWithCoder: (NSCoder *)coder 1745{ 1746 if ([coder allowsKeyedCoding]) 1747 { 1748 NSArray *nameKeys = nil; 1749 NSArray *nameValues = nil; 1750 NSArray *classKeys = nil; 1751 NSArray *classValues = nil; 1752 NSArray *objectsKeys = nil; 1753 NSArray *objectsValues = nil; 1754 NSArray *oidsKeys = nil; 1755 NSArray *oidsValues = nil; 1756 NSArray *accessibilityOidsKeys = nil; 1757 NSArray *accessibilityOidsValues = nil; 1758 1759 [(NSKeyedUnarchiver *)coder setClass: NSClassFromString(@"GSTableCornerView") 1760 forClassName: @"_NSCornerView"]; 1761 1762 // 1763 // Get root, font, framwork and oid. 1764 // Retain objects since NSKeyedUnarchiver autoreleases unarchived objects. 1765 // 1766 ASSIGN(_root, [coder decodeObjectForKey: @"NSRoot"]); 1767 ASSIGN(_fontManager, [coder decodeObjectForKey: @"NSFontManager"]); 1768 ASSIGN(_framework, [coder decodeObjectForKey: @"NSFramework"]); 1769 _nextOid = [coder decodeIntForKey: @"NSNextOid"]; 1770 1771 // get connections. 1772 ASSIGN(_connections, (NSMutableArray *) 1773 [coder decodeObjectForKey: @"NSConnections"]); 1774 ASSIGN(_accessibilityConnectors, (NSMutableArray *) 1775 [coder decodeObjectForKey: @"NSAccessibilityConnectors"]); 1776 1777 // get visible windows 1778 ASSIGN(_visibleWindows, (NSMutableArray *) 1779 [coder decodeObjectForKey: @"NSVisibleWindows"]); 1780 1781 // instantiate the maps.. 1782 _classes = NSCreateMapTable(NSObjectMapKeyCallBacks, 1783 NSObjectMapValueCallBacks, 2); 1784 _names = NSCreateMapTable(NSObjectMapKeyCallBacks, 1785 NSObjectMapValueCallBacks, 2); 1786 _objects = NSCreateMapTable(NSObjectMapKeyCallBacks, 1787 NSObjectMapValueCallBacks, 2); 1788 _oids = NSCreateMapTable(NSObjectMapKeyCallBacks, 1789 NSObjectMapValueCallBacks, 2); 1790 1791 // 1792 // Get the maps. There is no need to retain these, 1793 // since they are going to be placed into the NSMapTable 1794 // structures anyway. 1795 // 1796 nameKeys = (NSArray *) 1797 [coder decodeObjectForKey: @"NSNamesKeys"]; 1798 nameValues = (NSArray *) 1799 [coder decodeObjectForKey: @"NSNamesValues"]; 1800 classKeys = (NSArray *) 1801 [coder decodeObjectForKey: @"NSClassesKeys"]; 1802 classValues = (NSArray *) 1803 [coder decodeObjectForKey: @"NSClassesValues"]; 1804 objectsKeys = (NSArray *) 1805 [coder decodeObjectForKey: @"NSObjectsKeys"]; 1806 objectsValues = (NSArray *) 1807 [coder decodeObjectForKey: @"NSObjectsValues"]; 1808 oidsKeys = (NSArray *) 1809 [coder decodeObjectForKey: @"NSOidsKeys"]; 1810 oidsValues = (NSArray *) 1811 [coder decodeObjectForKey: @"NSOidsValues"]; 1812 1813 // Fill in the maps... 1814 [self _buildMap: _classes 1815 withKeys: classKeys 1816 andValues: classValues]; 1817 [self _buildMap: _names 1818 withKeys: nameKeys 1819 andValues: nameValues]; 1820 [self _buildMap: _objects 1821 withKeys: objectsKeys 1822 andValues: objectsValues]; 1823 [self _buildMap: _oids 1824 withKeys: oidsKeys 1825 andValues: oidsValues]; 1826 1827 // 1828 // Only get these maps when in the editor. They 1829 // aren't useful outside of it and only waste memory if 1830 // unarchived in the live application. 1831 // 1832 if ([NSClassSwapper isInInterfaceBuilder]) 1833 { 1834 // Only get these when in the editor... 1835 accessibilityOidsKeys = (NSArray *) 1836 [coder decodeObjectForKey: @"NSAccessibilityOidsKeys"]; 1837 accessibilityOidsValues = (NSArray *) 1838 [coder decodeObjectForKey: @"NSAccessibilityOidsValues"]; 1839 1840 _accessibilityOids = NSCreateMapTable(NSObjectMapKeyCallBacks, 1841 NSObjectMapValueCallBacks, 2); 1842 [self _buildMap: _accessibilityOids 1843 withKeys: accessibilityOidsKeys 1844 andValues: accessibilityOidsValues]; 1845 } 1846 1847 // instantiate... 1848 _topLevelObjects = [[NSMutableSet alloc] init]; 1849 } 1850 else 1851 { 1852 [NSException raise: NSInvalidArgumentException 1853 format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), 1854 NSStringFromClass([coder class])]; 1855 } 1856 1857 return self; 1858} 1859 1860/** 1861 * Initialize a new NSIBObjectData. 1862 */ 1863- (id) init 1864{ 1865 if ((self = [super init]) != nil) 1866 { 1867 // instantiate the maps.. 1868 _objects = NSCreateMapTable(NSObjectMapKeyCallBacks, 1869 NSObjectMapValueCallBacks, 2); 1870 _names = NSCreateMapTable(NSObjectMapKeyCallBacks, 1871 NSObjectMapValueCallBacks, 2); 1872 _oids = NSCreateMapTable(NSObjectMapKeyCallBacks, 1873 NSObjectMapValueCallBacks, 2); 1874 _classes = NSCreateMapTable(NSObjectMapKeyCallBacks, 1875 NSObjectMapValueCallBacks, 2); 1876 _accessibilityOids = NSCreateMapTable(NSObjectMapKeyCallBacks, 1877 NSObjectMapValueCallBacks, 2); 1878 1879 // initialize the objects... 1880 _accessibilityConnectors = [[NSMutableArray alloc] init]; 1881 _connections = [[NSMutableArray alloc] init]; 1882 _visibleWindows = [[NSMutableArray alloc] init]; 1883 _framework = nil; 1884 _fontManager = nil; 1885 _root = nil; 1886 _nextOid = 0; 1887 } 1888 return self; 1889} 1890 1891/** 1892 * Deallocate NSIBObjectData. 1893 */ 1894- (void) dealloc 1895{ 1896 // free the maps. 1897 NSFreeMapTable(_objects); 1898 NSFreeMapTable(_names); 1899 NSFreeMapTable(_classes); 1900 NSFreeMapTable(_oids); 1901 // these are not allocated when not in interface builder. 1902 if ([NSClassSwapper isInInterfaceBuilder]) 1903 { 1904 NSFreeMapTable(_accessibilityOids); 1905 } 1906 1907 // free other objects. 1908 RELEASE(_accessibilityConnectors); 1909 RELEASE(_connections); 1910 RELEASE(_fontManager); 1911 RELEASE(_framework); 1912 RELEASE(_visibleWindows); 1913 RELEASE(_root); 1914 RELEASE(_topLevelObjects); 1915 [super dealloc]; 1916} 1917 1918/** 1919 * Call nibInstantiate on an object, if it responds to the nibInstantiate selector. 1920 */ 1921- (id)instantiateObject: (id)obj 1922{ 1923 id newObject = obj; 1924 if ([obj respondsToSelector: @selector(nibInstantiate)]) 1925 { 1926 newObject = [obj nibInstantiate]; 1927 } 1928 return newObject; 1929} 1930 1931/** 1932 * Instantiate all of the objects in the nib file. 1933 */ 1934- (void) nibInstantiateWithOwner: (id)owner topLevelObjects: (NSMutableArray *)topLevelObjects 1935{ 1936 NSEnumerator *en; 1937 NSArray *objs; 1938 id obj = nil; 1939 id menu = nil; 1940 1941 // set the new root object. 1942 [_root setRealObject: owner]; 1943 1944 // iterate over all objects, instantiate them and fill in top level array. 1945 /* Note: We instantiate all objects before establishing any connections 1946 between them, so that any shared instances defined in the nib are 1947 initialized before being used. This sequence is important when, e.g., 1948 the nib defines a shared document controller that is an instance of a 1949 subclass of NSDocumentController. */ 1950 objs = NSAllMapTableKeys(_objects); 1951 en = [objs objectEnumerator]; 1952 while ((obj = [en nextObject]) != nil) 1953 { 1954 id v = NSMapGet(_objects, obj); 1955 NSInteger oid = [(id)NSMapGet(_oids, obj) intValue]; 1956 1957 obj = [self instantiateObject: obj]; 1958 // Object is top level if it isn't the owner but points to it. 1959 /* Don't record proxy objects in the top level array. The only 1960 reliable way to identify proxy objects seems to look at their 1961 object ID. Apparently, Apple is using fixed negative IDs for 1962 proxy objects (-1 = File's Owner, -2 = First Responder, 1963 -3 = NSApplication). */ 1964 if (oid >= 0) 1965 { 1966 if ((v == owner || v == _root) && (obj != owner) && (obj != _root)) 1967 { 1968 [topLevelObjects addObject: obj]; 1969 // All top level objects must be released by the caller to avoid 1970 // leaking, unless they are going to be released by other nib 1971 // objects on behalf of the owner. 1972 RETAIN(obj); 1973 } 1974 if ([obj isKindOfClass: [NSMenu class]] && 1975 [obj _isMainMenu]) 1976 { 1977 [NSApp _setMainMenu: obj]; 1978 } 1979 } 1980 } 1981 1982 // iterate over connections, instantiate and then establish them. 1983 en = [_connections objectEnumerator]; 1984 while ((obj = [en nextObject]) != nil) 1985 { 1986 if ([obj respondsToSelector: @selector(instantiateWithInstantiator:)]) 1987 { 1988 [obj instantiateWithInstantiator: self]; 1989 [obj establishConnection]; 1990 } 1991 else 1992 { 1993 if ([obj respondsToSelector: @selector(instantiateWithObjectInstantiator:)]) 1994 { 1995 [obj instantiateWithObjectInstantiator: self]; 1996 [obj establishConnection]; 1997 } 1998 } 1999 } 2000 2001 // awaken all objects except proxy objects. 2002 objs = NSAllMapTableKeys(_objects); 2003 en = [objs objectEnumerator]; 2004 while ((obj = [en nextObject]) != nil) 2005 { 2006 NSInteger oid = [(id)NSMapGet(_oids, obj) intValue]; 2007 if (oid >= 0) 2008 { 2009 if ([obj respondsToSelector: @selector(realObject)]) 2010 { 2011 obj = [obj realObject]; 2012 } 2013 if ([obj respondsToSelector: @selector(awakeFromNib)]) 2014 { 2015 [obj awakeFromNib]; 2016 } 2017 } 2018 } 2019 2020 // awaken the owner 2021 if ([owner respondsToSelector: @selector(awakeFromNib)]) 2022 { 2023 [owner awakeFromNib]; 2024 } 2025 2026 // bring visible windows to front... 2027 en = [_visibleWindows objectEnumerator]; 2028 while ((obj = [en nextObject]) != nil) 2029 { 2030 id w = [obj realObject]; 2031 [w orderFront: self]; 2032 } 2033 2034 // add the menu... 2035 menu = [self objectForName: @"MainMenu"]; 2036 if (menu != nil) 2037 { 2038 menu = [self instantiateObject: menu]; 2039 [NSApp _setMainMenu: menu]; 2040 } 2041} 2042 2043/** 2044 * Awake after loading the nib and extract the top level and owner for nib instantiation, 2045 * then call nibInstantateWithOwner:topLevelObjects: 2046 */ 2047- (void) awakeWithContext: (NSDictionary *)context 2048{ 2049 NSMutableArray *tlo = [context objectForKey: NSNibTopLevelObjects]; 2050 id owner = [context objectForKey: NSNibOwner]; 2051 2052 // instantiate... 2053 [self nibInstantiateWithOwner: owner topLevelObjects: tlo]; 2054} 2055 2056/** 2057 * Retrieve an object by name from the map. 2058 */ 2059- (id) objectForName: (NSString *)name 2060{ 2061 NSArray *nameKeys = (NSArray *)NSAllMapTableKeys(_names); 2062 NSArray *nameValues = (NSArray *)NSAllMapTableValues(_names); 2063 NSUInteger i = [nameValues indexOfObject: name]; 2064 id result = nil; 2065 2066 if (i != NSNotFound) 2067 { 2068 result = [nameKeys objectAtIndex: i]; 2069 } 2070 2071 return result; 2072} 2073 2074/** 2075 * Get the name for an object. 2076 */ 2077- (NSString *) nameForObject: (id)obj 2078{ 2079 NSArray *nameKeys = (NSArray *)NSAllMapTableKeys(_names); 2080 NSArray *nameValues = (NSArray *)NSAllMapTableValues(_names); 2081 int i = [nameKeys indexOfObject: obj]; 2082 NSString *result = [nameValues objectAtIndex: i]; 2083 return result; 2084} 2085 2086/** 2087 * Set the root object. 2088 */ 2089- (void) setRoot: (id) root 2090{ 2091 ASSIGN(_root, root); 2092} 2093 2094/** 2095 * Return the root object. 2096 */ 2097- (id) root 2098{ 2099 return _root; 2100} 2101 2102/** 2103 * Set the value of the next available oid. 2104 */ 2105- (void) setNextOid: (int)noid 2106{ 2107 _nextOid = noid; 2108} 2109 2110/** 2111 * Get the value of the next available oid. 2112 */ 2113- (int) nextOid 2114{ 2115 return _nextOid; 2116} 2117 2118/** 2119 * Connections between objects. 2120 */ 2121- (NSMutableArray *) connections 2122{ 2123 return _connections; 2124} 2125 2126/** 2127 * Set of top level objects. 2128 */ 2129- (NSMutableSet *) topLevelObjects 2130{ 2131 return _topLevelObjects; 2132} 2133 2134/** 2135 * Names to objects 2136 */ 2137- (NSMutableDictionary *) nameTable 2138{ 2139 return nil; 2140} 2141 2142/** 2143 * Set of all visible windows. 2144 */ 2145- (NSMutableArray *) visibleWindows 2146{ 2147 return _visibleWindows; 2148} 2149 2150/** 2151 * Objects to names table. 2152 */ 2153- (NSMapTable *) objects 2154{ 2155 return _objects; 2156} 2157 2158/** 2159 * Names to objects table. 2160 */ 2161- (NSMapTable *) names 2162{ 2163 return _names; 2164} 2165 2166/** 2167 * Classes to objects table. 2168 */ 2169- (NSMapTable *) classes 2170{ 2171 return _classes; 2172} 2173 2174/** 2175 * Oids to objects table. 2176 */ 2177- (NSMapTable *) oids 2178{ 2179 return _oids; 2180} 2181@end 2182 2183/** 2184 * NSButtonImageSource 2185 * 2186 * This class is used by buttons to pull the correct image based on a given state. 2187 */ 2188@implementation NSButtonImageSource 2189- (id) initWithCoder: (NSCoder *)coder 2190{ 2191 if ([coder allowsKeyedCoding]) 2192 { 2193 ASSIGN(imageName, [coder decodeObjectForKey: @"NSImageName"]); 2194 } 2195 else 2196 { 2197 [NSException raise: NSInvalidArgumentException 2198 format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), 2199 NSStringFromClass([coder class])]; 2200 } 2201 2202 AUTORELEASE(self); 2203 return RETAIN([NSImage imageNamed: imageName]); 2204} 2205 2206- (void) encodeWithCoder: (NSCoder *)coder 2207{ 2208 if ([coder allowsKeyedCoding]) 2209 { 2210 [coder encodeObject: imageName forKey: @"NSImageName"]; 2211 } 2212 else 2213 { 2214 [NSException raise: NSInvalidArgumentException 2215 format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), 2216 NSStringFromClass([coder class])]; 2217 } 2218} 2219 2220/** 2221 * Initializes with image name. 2222 */ 2223- (id) initWithImageNamed: (NSString *)name 2224{ 2225 if ((self = [super init]) != nil) 2226 { 2227 ASSIGN(imageName,name); 2228 } 2229 return self; 2230} 2231 2232/** 2233 * Returns imageName. 2234 */ 2235- (NSString *)imageName 2236{ 2237 return imageName; 2238} 2239 2240- (void) dealloc 2241{ 2242 RELEASE(imageName); 2243 [super dealloc]; 2244} 2245@end 2246 2247@implementation NSIBHelpConnector 2248- (id) init 2249{ 2250 if ((self = [super init]) != nil) 2251 { 2252 _file = nil; 2253 ASSIGN(_marker, @"NSToolTipHelpKey"); 2254 } 2255 return self; 2256} 2257 2258- (void) dealloc 2259{ 2260 RELEASE(_file); 2261 RELEASE(_marker); 2262 [super dealloc]; 2263} 2264 2265- (id) initWithCoder: (NSCoder *)coder 2266{ 2267 if ((self = [super initWithCoder: coder]) != nil) 2268 { 2269 if ([coder allowsKeyedCoding]) 2270 { 2271 if ([coder containsValueForKey: @"NSFile"]) 2272 { 2273 ASSIGN(_file, [coder decodeObjectForKey: @"NSFile"]); 2274 } 2275 if ([coder containsValueForKey: @"NSMarker"]) 2276 { 2277 ASSIGN(_marker, [coder decodeObjectForKey: @"NSMarker"]); 2278 } 2279 } 2280 else 2281 { 2282 ASSIGN(_file, [coder decodeObject]); 2283 ASSIGN(_marker, [coder decodeObject]); 2284 } 2285 } 2286 return self; 2287} 2288 2289- (void) encodeWithCoder: (NSCoder *)coder 2290{ 2291 [super encodeWithCoder: coder]; 2292 if ([coder allowsKeyedCoding]) 2293 { 2294 if (_file != nil) 2295 { 2296 [coder encodeObject: _file forKey: @"NSFile"]; 2297 } 2298 if (_marker != nil) 2299 { 2300 [coder encodeObject: _marker forKey: @"NSMarker"]; 2301 } 2302 } 2303 else 2304 { 2305 [coder encodeObject: _file]; 2306 [coder encodeObject: _marker]; 2307 } 2308} 2309 2310- (void) establishConnection 2311{ 2312 if ([_dst respondsToSelector: @selector(setToolTip:)]) 2313 { 2314 [_dst setToolTip: _marker]; 2315 } 2316} 2317 2318- (void) setFile: (id)file 2319{ 2320 ASSIGN(_file, file); 2321} 2322 2323- (id) file 2324{ 2325 return _file; 2326} 2327 2328- (void) setMarker: (id)marker 2329{ 2330 ASSIGN(_marker, marker); 2331} 2332 2333- (id) marker 2334{ 2335 return _marker; 2336} 2337@end 2338 2339@implementation NSDecimalNumberPlaceholder 2340- (id) initWithCoder: (NSCoder *)coder 2341{ 2342 NSDecimalNumber *dn = nil; 2343 if ([coder allowsKeyedCoding]) 2344 { 2345 NSUInteger len = 0; 2346 short exponent = (short)[coder decodeIntForKey: @"NS.exponent"]; 2347 NSByteOrder bo = [coder decodeIntForKey: @"NS.mantissa.bo"]; 2348 BOOL negative = [coder decodeBoolForKey: @"NS.negative"]; 2349 void *mantissaBytes = (void *)[coder decodeBytesForKey: @"NS.mantissa" returnedLength: &len]; 2350 unsigned long long unswapped = 0; 2351 unsigned long long mantissa = 0; 2352 2353 // BOOL compact = [coder decodeBoolForKey: @"NS.compact"]; 2354 // int length = [coder decodeIntForKey: @"NS.length"]; 2355 2356 memcpy((void *)&unswapped, (void *)mantissaBytes, sizeof(unsigned long long)); 2357 2358 switch(bo) 2359 { 2360 case NS_BigEndian: 2361 mantissa = NSSwapBigLongLongToHost(unswapped); 2362 break; 2363 case NS_LittleEndian: 2364 mantissa = NSSwapLittleLongLongToHost(unswapped); 2365 break; 2366 default: 2367 break; 2368 } 2369 2370 dn = [[NSDecimalNumber alloc] initWithMantissa: mantissa 2371 exponent: exponent 2372 isNegative: negative]; 2373 } 2374 2375 RELEASE(self); 2376 return (id)dn; 2377} 2378 2379@end 2380 2381/** 2382 * NSCornerView 2383 * 2384 * Overridden in NSTableView to be GSTableCornerView, 2385 * but the class needs to be present to be overridden. 2386 * 2387 * Currently this is a place-holder class. 2388 */ 2389@implementation _NSCornerView 2390@end 2391 2392/** 2393 * NSPSMatrix. 2394 * 2395 * This class is needed for nib encoding/decoding by transforms. 2396 * Currently it's only referenced in the NSProgressIndicator, 2397 * as far as I can tell. 2398 * 2399 * Place holder class. 2400 */ 2401@implementation NSPSMatrix 2402- (void) encodeWithCoder: (NSCoder *)coder 2403{ 2404 // do nothing... just encoding the presence of the class. 2405} 2406 2407- (id) initWithCoder: (NSCoder *)coder 2408{ 2409 return self; 2410} 2411@end 2412 2413@implementation NSIBUserDefinedRuntimeAttributesConnector 2414- (void) setObject: (id)object 2415{ 2416 ASSIGN(_object, object); 2417} 2418 2419- (id) object 2420{ 2421 return _object; 2422} 2423 2424- (void) setValues: (id)values 2425{ 2426 ASSIGN(_values, values); 2427} 2428 2429- (id) values 2430{ 2431 return _values; 2432} 2433 2434- (void) setKeyPaths: (id)keyPaths 2435{ 2436 ASSIGN(_keyPaths, keyPaths); 2437} 2438 2439- (id) keyPaths 2440{ 2441 return _keyPaths; 2442} 2443 2444- (void) dealloc 2445{ 2446 RELEASE(_object); 2447 RELEASE(_keyPaths); 2448 RELEASE(_values); 2449 [super dealloc]; 2450} 2451 2452- (void) encodeWithCoder: (NSCoder *)coder 2453{ 2454 if ([coder allowsKeyedCoding]) 2455 { 2456 if (_object != nil) 2457 { 2458 [coder encodeObject: _object forKey: @"NSObject"]; 2459 } 2460 if (_keyPaths != nil) 2461 { 2462 [coder encodeObject: _keyPaths forKey: @"NSKeyPaths"]; 2463 } 2464 if (_values != nil) 2465 { 2466 [coder encodeObject: _values forKey: @"NSValues"]; 2467 } 2468 } 2469 else 2470 { 2471 [coder encodeObject: _object]; 2472 [coder encodeObject: _keyPaths]; 2473 [coder encodeObject: _values]; 2474 } 2475} 2476 2477- (id) initWithCoder: (NSCoder *)coder 2478{ 2479 if ([coder allowsKeyedCoding]) 2480 { 2481 if ([coder containsValueForKey: @"NSObject"]) 2482 { 2483 ASSIGN(_object, [coder decodeObjectForKey: @"NSObject"]); 2484 } 2485 if ([coder containsValueForKey: @"NSKeyPaths"]) 2486 { 2487 ASSIGN(_keyPaths, [coder decodeObjectForKey: @"NSKeyPaths"]); 2488 } 2489 if ([coder containsValueForKey: @"NSValues"]) 2490 { 2491 ASSIGN(_values, [coder decodeObjectForKey: @"NSValues"]); 2492 } 2493 } 2494 else 2495 { 2496 ASSIGN(_object, [coder decodeObject]); 2497 ASSIGN(_keyPaths, [coder decodeObject]); 2498 ASSIGN(_values, [coder decodeObject]); 2499 } 2500 2501 return self; 2502} 2503 2504- (void) establishConnection 2505{ 2506 // Loop over key paths and values and use KVC on object 2507 NSEnumerator *keyEn = [_keyPaths objectEnumerator]; 2508 NSEnumerator *valEn = [_values objectEnumerator]; 2509 id key; 2510 2511 while ((key = [keyEn nextObject]) != nil) 2512 { 2513 id val = [valEn nextObject]; 2514 2515 [_object setValue: val forKeyPath: key]; 2516 } 2517} 2518 2519- (void) instantiateWithObjectInstantiator: (id)instantiator 2520{ 2521 [self setObject: [(id<GSInstantiator>)instantiator instantiateObject: _object]]; 2522 // FIXME Should handle values too 2523} 2524 2525@end 2526