/[gnustep]/gnustep/core/gui/Source/GSNibTemplates.m
ViewVC logotype

Contents of /gnustep/core/gui/Source/GSNibTemplates.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (show annotations) (download)
Mon Sep 1 09:21:46 2003 UTC (20 years, 7 months ago) by gcasa
Branch: MAIN
Changes since 1.6: +10 -9 lines
Corrected mainMenu initialization problem

1 /** <title>GSNibTemplates</title>
2
3 <abstract>Contains all of the private classes used in .gorm files.</abstract>
4
5 Copyright (C) 2003 Free Software Foundation, Inc.
6
7 Author: Gregory John Casamento
8 Date: July 2003.
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 Library 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 Library General Public License for more details.
21
22 You should have received a copy of the GNU Library General Public
23 License along with this library;
24 If not, write to the Free Software Foundation,
25 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 // #include "gnustep/gui/config.h"
29 #include <Foundation/NSClassDescription.h>
30 #include <Foundation/NSArchiver.h>
31 #include <Foundation/NSArray.h>
32 #include <Foundation/NSBundle.h>
33 #include <Foundation/NSCoder.h>
34 #include <Foundation/NSData.h>
35 #include <Foundation/NSDictionary.h>
36 #include <Foundation/NSDebug.h>
37 #include <Foundation/NSEnumerator.h>
38 #include <Foundation/NSException.h>
39 #include <Foundation/NSInvocation.h>
40 #include <Foundation/NSObjCRuntime.h>
41 #include <Foundation/NSPathUtilities.h>
42 #include <Foundation/NSFileManager.h>
43 #include <Foundation/NSString.h>
44 #include <Foundation/NSUserDefaults.h>
45 #include <Foundation/NSKeyValueCoding.h>
46 #include "AppKit/NSMenu.h"
47 #include "AppKit/NSControl.h"
48 #include "AppKit/NSImage.h"
49 #include "AppKit/NSSound.h"
50 #include "AppKit/NSView.h"
51 #include "AppKit/NSTextView.h"
52 #include "AppKit/NSWindow.h"
53 #include <AppKit/NSNibLoading.h>
54 #include <AppKit/NSNibConnector.h>
55 #include <AppKit/NSApplication.h>
56 #include <GNUstepBase/GSObjCRuntime.h>
57 #include <GNUstepGUI/GSNibTemplates.h>
58
59 static const int currentVersion = 1; // GSNibItem version number...
60
61 @interface NSApplication (GSNibContainer)
62 - (void)_deactivateVisibleWindow: (NSWindow *)win;
63 @end
64
65 @implementation NSApplication (GSNibContainer)
66 /* Since awakeWithContext often gets called before the the app becomes
67 active, [win -orderFront:] requests get ignored, so we add the window
68 to the inactive list, so it gets sent an -orderFront when the app
69 becomes active. */
70 - (void) _deactivateVisibleWindow: (NSWindow *)win
71 {
72 if (_inactive)
73 [_inactive addObject: win];
74 }
75 @end
76
77 /*
78 * The GSNibContainer class manages the internals of a nib file.
79 */
80 @implementation GSNibContainer
81
82 + (void) initialize
83 {
84 if (self == [GSNibContainer class])
85 {
86 [self setVersion: GNUSTEP_NIB_VERSION];
87 }
88 }
89
90 - (void) awakeWithContext: (NSDictionary*)context
91 {
92 if (_isAwake == NO)
93 {
94 NSEnumerator *enumerator;
95 NSNibConnector *connection;
96 NSString *key;
97 NSArray *visible;
98 NSMenu *menu;
99
100 _isAwake = YES;
101 /*
102 * Add local entries into name table.
103 */
104 if ([context count] > 0)
105 {
106 [nameTable addEntriesFromDictionary: context];
107 }
108
109 /*
110 * Now establish all connections by taking the names
111 * stored in the connection objects, and replaciong them
112 * with the corresponding values from the name table
113 * before telling the connections to establish themselves.
114 */
115 enumerator = [connections objectEnumerator];
116 while ((connection = [enumerator nextObject]) != nil)
117 {
118 id val;
119
120 val = [nameTable objectForKey: [connection source]];
121 [connection setSource: val];
122 val = [nameTable objectForKey: [connection destination]];
123 [connection setDestination: val];
124 [connection establishConnection];
125 // release the connections, now that they have been established.
126 RELEASE(connection);
127 }
128
129 /*
130 * See if there is a main menu to be set. Report #4815, mainMenu
131 * should be initialized before awakeFromNib is called.
132 */
133 menu = [nameTable objectForKey: @"NSMenu"];
134 if (menu != nil && [menu isKindOfClass: [NSMenu class]] == YES)
135 {
136 [NSApp setMainMenu: menu];
137 }
138
139 /*
140 * Now tell all the objects that they have been loaded from
141 * a nib.
142 */
143 enumerator = [nameTable keyEnumerator];
144 while ((key = [enumerator nextObject]) != nil)
145 {
146 if ([context objectForKey: key] == nil ||
147 [key isEqualToString: @"NSOwner"]) // we want to send the message to the owner
148 {
149 id o;
150
151 o = [nameTable objectForKey: key];
152 if ([o respondsToSelector: @selector(awakeFromNib)])
153 {
154 [o awakeFromNib];
155 }
156 }
157 }
158
159 /*
160 * See if there are objects that should be made visible.
161 */
162 visible = [nameTable objectForKey: @"NSVisible"];
163 if (visible != nil
164 && [visible isKindOfClass: [NSArray class]] == YES)
165 {
166 unsigned pos = [visible count];
167
168 while (pos-- > 0)
169 {
170 NSWindow *win = [visible objectAtIndex: pos];
171 if ([NSApp isActive])
172 [win orderFront: self];
173 else
174 [NSApp _deactivateVisibleWindow: win];
175 }
176 }
177
178 /*
179 * Now remove any objects added from the context dictionary.
180 */
181 if ([context count] > 0)
182 {
183 [nameTable removeObjectsForKeys: [context allKeys]];
184 }
185 }
186 }
187
188 - (NSMutableArray*) connections
189 {
190 return connections;
191 }
192
193 - (void) dealloc
194 {
195 RELEASE(nameTable);
196 RELEASE(connections);
197 [super dealloc];
198 }
199
200 - (void) encodeWithCoder: (NSCoder*)aCoder
201 {
202 [aCoder encodeObject: nameTable];
203 [aCoder encodeObject: connections];
204 }
205
206 - (id) init
207 {
208 if ((self = [super init]) != nil)
209 {
210 nameTable = [[NSMutableDictionary alloc] initWithCapacity: 8];
211 connections = [[NSMutableArray alloc] initWithCapacity: 8];
212 }
213 return self;
214 }
215
216 - (id) initWithCoder: (NSCoder*)aCoder
217 {
218 int version = [aCoder versionForClassName: @"GSNibContainer"];
219
220 if(version == GNUSTEP_NIB_VERSION)
221 {
222 [aCoder decodeValueOfObjCType: @encode(id) at: &nameTable];
223 [aCoder decodeValueOfObjCType: @encode(id) at: &connections];
224 }
225
226 return self;
227 }
228
229 - (NSMutableDictionary*) nameTable
230 {
231 return nameTable;
232 }
233 @end
234
235 // The first standin objects here are for views and normal objects like controllers
236 // or data sources.
237 @implementation GSNibItem
238 + (void) initialize
239 {
240 if (self == [GSNibItem class])
241 {
242 [self setVersion: currentVersion];
243 }
244 }
245
246 - (void) dealloc
247 {
248 RELEASE(theClass);
249 [super dealloc];
250 }
251
252 - (void) encodeWithCoder: (NSCoder*)aCoder
253 {
254 [aCoder encodeObject: theClass];
255 [aCoder encodeRect: theFrame];
256 [aCoder encodeValueOfObjCType: @encode(unsigned int)
257 at: &autoresizingMask];
258 }
259
260 - (id) initWithCoder: (NSCoder*)aCoder
261 {
262 int version = [aCoder versionForClassName:
263 NSStringFromClass([self class])];
264
265 if (version == 1)
266 {
267 id obj;
268 Class cls;
269 unsigned int mask;
270
271 [aCoder decodeValueOfObjCType: @encode(id) at: &theClass];
272 theFrame = [aCoder decodeRect];
273 [aCoder decodeValueOfObjCType: @encode(unsigned int)
274 at: &mask];
275
276 cls = NSClassFromString(theClass);
277 if (cls == nil)
278 {
279 [NSException raise: NSInternalInconsistencyException
280 format: @"Unable to find class '%@'", theClass];
281 }
282
283 obj = [cls allocWithZone: [self zone]];
284 if (theFrame.size.height > 0 && theFrame.size.width > 0)
285 obj = [obj initWithFrame: theFrame];
286 else
287 obj = [obj init];
288
289 if ([obj respondsToSelector: @selector(setAutoresizingMask:)])
290 {
291 [obj setAutoresizingMask: mask];
292 }
293
294 RELEASE(self);
295 return obj;
296 }
297 else if (version == 0)
298 {
299 id obj;
300 Class cls;
301
302 [aCoder decodeValueOfObjCType: @encode(id) at: &theClass];
303 theFrame = [aCoder decodeRect];
304
305 cls = NSClassFromString(theClass);
306 if (cls == nil)
307 {
308 [NSException raise: NSInternalInconsistencyException
309 format: @"Unable to find class '%@'", theClass];
310 }
311
312 obj = [cls allocWithZone: [self zone]];
313 if (theFrame.size.height > 0 && theFrame.size.width > 0)
314 obj = [obj initWithFrame: theFrame];
315 else
316 obj = [obj init];
317
318 RELEASE(self);
319 return obj;
320 }
321 else
322 {
323 NSLog(@"no initWithCoder for this version");
324 RELEASE(self);
325 return nil;
326 }
327 }
328
329 @end
330
331 @implementation GSCustomView
332 + (void) initialize
333 {
334 if (self == [GSCustomView class])
335 {
336 [self setVersion: currentVersion];
337 }
338 }
339
340 - (void) encodeWithCoder: (NSCoder*)aCoder
341 {
342 [super encodeWithCoder: aCoder];
343 }
344
345 - (id) initWithCoder: (NSCoder*)aCoder
346 {
347 return [super initWithCoder: aCoder];
348 }
349 @end
350
351 /*
352 These stand-ins are here for use by GUI elements within Gorm. Since each gui element
353 has it's own "designated initializer" it's important to provide a division between these
354 so that when they are loaded, the application will call the correct initializer.
355
356 Some "tricks" are employed in this code. For instance the use of initWithCoder and
357 encodeWithCoder directly as opposed to using the encodeObjC.. methods is the obvious
358 standout. To understand this it's necessary to explain a little about how encoding itself
359 works.
360
361 When the model is saved by the Interface Builder (whether Gorm or another
362 IB equivalent) these classes should be used to substitute for the actual classes. The actual
363 classes are encoded as part of it, but since they are being replaced we can't use the normal
364 encode methods to do it and must encode it directly.
365
366 Also, the reason for encoding the superclass itself is that by doing so the unarchiver knows
367 what version is referred to by the encoded object. This way we can replace the object with
368 a substitute class which will allow it to create itself as the custom class when read it by
369 the application, and using the encoding system to do it in a clean way.
370 */
371 @implementation GSClassSwapper
372 + (void) initialize
373 {
374 if (self == [GSClassSwapper class])
375 {
376 [self setVersion: GSSWAPPER_VERSION];
377 }
378 }
379
380 - (id) initWithObject: (id)object className: (NSString *)className superClassName: (NSString *)superClassName
381 {
382 if((self = [self init]) != nil)
383 {
384 NSDebugLog(@"Created template %@ -> %@",NSStringFromClass([self class]), className);
385 ASSIGN(_object, object);
386 ASSIGN(_className, [className copy]);
387 NSAssert(![className isEqualToString: superClassName], NSInvalidArgumentException);
388 _superClass = NSClassFromString(superClassName);
389 if(_superClass == nil)
390 {
391 [NSException raise: NSInternalInconsistencyException
392 format: @"Unable to find class '%@'", superClassName];
393 }
394 }
395 return self;
396 }
397
398 - init
399 {
400 if((self = [super init]) != nil)
401 {
402 _className = nil;
403 _superClass = nil;
404 _object = nil;
405 }
406 return self;
407 }
408
409 - (void) setClassName: (NSString *)name
410 {
411 ASSIGN(_className, [name copy]);
412 }
413
414 - (NSString *)className
415 {
416 return _className;
417 }
418
419 - (id) initWithCoder: (NSCoder *)coder
420 {
421 id obj = nil;
422 int version = [coder versionForClassName: @"GSClassSwapper"];
423 if(version == 0)
424 {
425 if((self = [super init]) != nil)
426 {
427 // decode class/superclass...
428 [coder decodeValueOfObjCType: @encode(id) at: &_className];
429 [coder decodeValueOfObjCType: @encode(Class) at: &_superClass];
430
431 // if we are living within the interface builder app, then don't try to
432 // morph into the subclass.
433 if([self respondsToSelector: @selector(isInInterfaceBuilder)])
434 {
435 obj = [[_superClass alloc] initWithCoder: coder]; // unarchive the object...
436 }
437 else
438 {
439 Class aClass = NSClassFromString(_className);
440 if(aClass == 0)
441 {
442 [NSException raise: NSInternalInconsistencyException
443 format: @"Unable to find class '%@'", _className];
444 }
445
446 // Initialize the object... dont call decode, since this wont
447 // allow us to instantiate the class we want.
448 obj = [[aClass alloc] initWithCoder: coder]; // unarchive the object...
449 }
450 }
451 }
452
453 // Do this here since we are not using decode to do this.
454 // Normally decode does a retain, so we must do it here.
455 RETAIN(obj);
456
457 // change the class of the instance to the one we want to see...
458 return obj;
459 }
460
461 - (void) encodeWithCoder: (NSCoder *)aCoder
462 {
463 [aCoder encodeValueOfObjCType: @encode(id) at: &_className];
464 [aCoder encodeValueOfObjCType: @encode(Class) at: &_superClass];
465
466 if(_object != nil)
467 {
468 // Don't call encodeValue, the way templates are used will prevent
469 // it from being saved correctly. Just call encodeWithCoder directly.
470 [_object encodeWithCoder: aCoder];
471 }
472 }
473 @end
474
475 @implementation GSWindowTemplate
476 + (void) initialize
477 {
478 if (self == [GSWindowTemplate class])
479 {
480 [self setVersion: GSWINDOWT_VERSION];
481 }
482 }
483
484 - (BOOL)deferFlag
485 {
486 return _deferFlag;
487 }
488
489 - (void)setDeferFlag: (BOOL)flag
490 {
491 _deferFlag = flag;
492 }
493
494 // NSCoding...
495 - (id) initWithCoder: (NSCoder *)coder
496 {
497 id obj = [super initWithCoder: coder];
498 if(obj != nil)
499 {
500 NSView *contentView = nil;
501
502 // decode the defer flag...
503 [coder decodeValueOfObjCType: @encode(BOOL) at: &_deferFlag];
504
505 if(![self respondsToSelector: @selector(isInInterfaceBuilder)])
506 {
507 if(GSGetInstanceMethodNotInherited([obj class], @selector(initWithContentRect:styleMask:backing:defer:)) != NULL)
508 {
509 // if we are not in interface builder, call
510 // designated initializer per spec...
511 contentView = [obj contentView];
512 obj = [obj initWithContentRect: [obj frame]
513 styleMask: [obj styleMask]
514 backing: [obj backingType]
515 defer: _deferFlag];
516
517 // set the content view back
518 [obj setContentView: contentView];
519 }
520 }
521 RELEASE(self);
522 }
523 return obj;
524 }
525
526 - (void) encodeWithCoder: (NSCoder *)coder
527 {
528 [super encodeWithCoder: coder];
529 [coder encodeValueOfObjCType: @encode(BOOL) at: &_deferFlag];
530 }
531 @end
532
533 @implementation GSViewTemplate
534 + (void) initialize
535 {
536 if (self == [GSViewTemplate class])
537 {
538 [self setVersion: GSVIEWT_VERSION];
539 }
540 }
541
542 - (id) initWithCoder: (NSCoder *)coder
543 {
544 id obj = [super initWithCoder: coder];
545 if(obj != nil)
546 {
547 if(![self respondsToSelector: @selector(isInInterfaceBuilder)])
548 {
549 if(GSGetInstanceMethodNotInherited([obj class],@selector(initWithFrame:)) != NULL)
550 {
551 NSRect theFrame = [obj frame];
552 obj = [obj initWithFrame: theFrame];
553 }
554 }
555 RELEASE(self);
556 }
557 return obj;
558 }
559 @end
560
561 // Template for any classes which derive from NSText
562 @implementation GSTextTemplate
563 + (void) initialize
564 {
565 if (self == [GSTextTemplate class])
566 {
567 [self setVersion: GSTEXTT_VERSION];
568 }
569 }
570
571 - (id) initWithCoder: (NSCoder *)coder
572 {
573 id obj = [super initWithCoder: coder];
574 if(obj != nil)
575 {
576 if(![self respondsToSelector: @selector(isInInterfaceBuilder)])
577 {
578 if(GSGetInstanceMethodNotInherited([obj class],@selector(initWithFrame:)) != NULL)
579 {
580 NSRect theFrame = [obj frame];
581 obj = [obj initWithFrame: theFrame];
582 }
583 }
584 RELEASE(self);
585 }
586 return obj;
587 }
588 @end
589
590 // Template for any classes which derive from GSTextView
591 @implementation GSTextViewTemplate
592 + (void) initialize
593 {
594 if (self == [GSTextViewTemplate class])
595 {
596 [self setVersion: GSTEXTVIEWT_VERSION];
597 }
598 }
599
600 - (id) initWithCoder: (NSCoder *)coder
601 {
602 id obj = [super initWithCoder: coder];
603 if(obj != nil)
604 {
605 if(![self respondsToSelector: @selector(isInInterfaceBuilder)])
606 {
607 if(GSGetInstanceMethodNotInherited([obj class],@selector(initWithFrame:textContainer:)) != NULL)
608 {
609 NSRect theFrame = [obj frame];
610 id textContainer = [obj textContainer];
611 obj = [obj initWithFrame: theFrame
612 textContainer: textContainer];
613 }
614 }
615 RELEASE(self);
616 }
617 return obj;
618 }
619 @end
620
621 // Template for any classes which derive from NSMenu.
622 @implementation GSMenuTemplate
623 + (void) initialize
624 {
625 if (self == [GSMenuTemplate class])
626 {
627 [self setVersion: GSMENUT_VERSION];
628 }
629 }
630
631 - (id) initWithCoder: (NSCoder *)coder
632 {
633 id obj = [super initWithCoder: coder];
634 if(obj != nil)
635 {
636 if(![self respondsToSelector: @selector(isInInterfaceBuilder)])
637 {
638 if(GSGetInstanceMethodNotInherited([obj class],@selector(initWithTitle:)) != NULL)
639 {
640 NSString *theTitle = [obj title];
641 obj = [obj initWithTitle: theTitle];
642 }
643 }
644 RELEASE(self);
645 }
646 return obj;
647 }
648 @end
649
650
651 // Template for any classes which derive from NSControl
652 @implementation GSControlTemplate
653 + (void) initialize
654 {
655 if (self == [GSControlTemplate class])
656 {
657 [self setVersion: GSCONTROLT_VERSION];
658 }
659 }
660
661 - (id) initWithCoder: (NSCoder *)coder
662 {
663 id obj = [super initWithCoder: coder];
664 if(obj != nil)
665 {
666 if(![self respondsToSelector: @selector(isInInterfaceBuilder)])
667 {
668 if(GSGetInstanceMethodNotInherited([obj class],@selector(initWithFrame:)) != NULL)
669 {
670 NSRect theFrame = [obj frame];
671 obj = [obj initWithFrame: theFrame];
672 }
673 }
674 RELEASE(self);
675 }
676 return obj;
677 }
678 @end
679
680 @implementation GSObjectTemplate
681 + (void) initialize
682 {
683 if (self == [GSObjectTemplate class])
684 {
685 [self setVersion: GSOBJECTT_VERSION];
686 }
687 }
688
689 - (id) initWithCoder: (NSCoder *)coder
690 {
691 id obj = [super initWithCoder: coder];
692 if(obj != nil)
693 {
694 if(![self respondsToSelector: @selector(isInInterfaceBuilder)])
695 {
696 if(GSGetInstanceMethodNotInherited([obj class],@selector(init)) != NULL)
697 {
698 obj = [self init];
699 }
700 }
701 RELEASE(self);
702 }
703 return obj;
704 }
705 @end
706
707 @interface NSObject (NibInstantiation)
708 - (id) nibInstantiate;
709 @end
710
711 @implementation NSObject (NibInstantiation)
712 - (id) nibInstantiate
713 {
714 // default implementation of nibInstantiate
715 return self;
716 }
717 @end
718
719 // Order in this factory method is very important. Which template to create must be determined
720 // in sequence because of the class hierarchy.
721 @implementation GSTemplateFactory
722 + (id) templateForObject: (id) object
723 withClassName: (NSString *)className
724 withSuperClassName: (NSString *)superClassName
725 {
726 id template = nil;
727 if(object != nil)
728 {
729 // NSData *objectData = nil;
730 // [archiver encodeRootObject: object];
731 // objectData = [archiver archiverData];
732 if ([object isKindOfClass: [NSWindow class]])
733 {
734 template = [[GSWindowTemplate alloc] initWithObject: object
735 className: className
736 superClassName: superClassName];
737 }
738 else if ([object isKindOfClass: [NSTextView class]])
739 {
740 template = [[GSTextViewTemplate alloc] initWithObject: object
741 className: className
742 superClassName: superClassName];
743 }
744 else if ([object isKindOfClass: [NSText class]])
745 {
746 template = [[GSTextTemplate alloc] initWithObject: object
747 className: className
748 superClassName: superClassName];
749 }
750 else if ([object isKindOfClass: [NSControl class]])
751 {
752 template = [[GSControlTemplate alloc] initWithObject: object
753 className: className
754 superClassName: superClassName];
755 }
756 else if ([object isKindOfClass: [NSView class]])
757 {
758 template = [[GSViewTemplate alloc] initWithObject: object
759 className: className
760 superClassName: superClassName];
761 }
762 else if ([object isKindOfClass: [NSMenu class]])
763 {
764 template = [[GSMenuTemplate alloc] initWithObject: object
765 className: className
766 superClassName: superClassName];
767 }
768 else if ([object isKindOfClass: [NSObject class]]) // for gui elements derived from NSObject
769 {
770 template = [[GSObjectTemplate alloc] initWithObject: object
771 className: className
772 superClassName: superClassName];
773 }
774 }
775 return template;
776 }
777 @end
778
779 //////////////////////////////////////////////////////////////////////////////////////////
780 ////////////////// DEPRECATED TEMPLATES ----- THESE SHOULD NOT BE USED //////////////////
781 //////////////////////////////////////////////////////////////////////////////////////////
782
783 /*
784 These templates are from the old system, which had some issues. Currently I believe
785 that NSWindowTemplate was the only one seeing use, so it is the only one included.
786 if any more are needed they will be added back.
787
788 As these classes are deprecated, they should disappear from the gnustep distribution
789 in the next major release.
790 */
791
792 @implementation NSWindowTemplate
793 + (void) initialize
794 {
795 if (self == [NSWindowTemplate class])
796 {
797 [self setVersion: 0];
798 }
799 }
800
801 - (void) dealloc
802 {
803 RELEASE(_parentClassName);
804 RELEASE(_className);
805 [super dealloc];
806 }
807
808 - init
809 {
810 [super init];
811
812 // Start initially with the highest level class...
813 ASSIGN(_className, NSStringFromClass([super class]));
814 ASSIGN(_parentClassName, NSStringFromClass([super class]));
815
816 // defer flag...
817 _deferFlag = NO;
818
819 return self;
820 }
821
822 - (id) initWithCoder: (NSCoder *)aCoder
823 {
824 [aCoder decodeValueOfObjCType: @encode(id) at: &_className];
825 [aCoder decodeValueOfObjCType: @encode(id) at: &_parentClassName];
826 [aCoder decodeValueOfObjCType: @encode(BOOL) at: &_deferFlag];
827 return [super initWithCoder: aCoder];
828 }
829
830 - (void) encodeWithCoder: (NSCoder *)aCoder
831 {
832 [aCoder encodeValueOfObjCType: @encode(id) at: &_className];
833 [aCoder encodeValueOfObjCType: @encode(id) at: &_parentClassName];
834 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &_deferFlag];
835 [super encodeWithCoder: aCoder];
836 }
837
838 - (id) awakeAfterUsingCoder: (NSCoder *)coder
839 {
840 if([self respondsToSelector: @selector(isInInterfaceBuilder)])
841 {
842 // if we live in the interface builder, give them an instance of
843 // the parent, not the child..
844 [self setClassName: _parentClassName];
845 }
846
847 return [self instantiateObject: coder];
848 }
849
850 - (id) instantiateObject: (NSCoder *)coder
851 {
852 id obj = nil;
853 Class aClass = NSClassFromString(_className);
854
855 if (aClass == nil)
856 {
857 [NSException raise: NSInternalInconsistencyException
858 format: @"Unable to find class '%@'", _className];
859 }
860
861 obj = [[aClass allocWithZone: [self zone]]
862 initWithContentRect: [self frame]
863 styleMask: [self styleMask]
864 backing: [self backingType]
865 defer: _deferFlag];
866
867 // fill in actual object from template...
868 [obj setBackgroundColor: [self backgroundColor]];
869 [(NSWindow*)obj setContentView: [self contentView]];
870 [obj setFrameAutosaveName: [self frameAutosaveName]];
871 [obj setHidesOnDeactivate: [self hidesOnDeactivate]];
872 [obj setInitialFirstResponder: [self initialFirstResponder]];
873 [obj setAutodisplay: [self isAutodisplay]];
874 [obj setReleasedWhenClosed: [self isReleasedWhenClosed]];
875 [obj _setVisible: [self isVisible]];
876 [obj setTitle: [self title]];
877 [obj setFrame: [self frame] display: NO];
878
879 RELEASE(self);
880 return obj;
881 }
882
883 // setters and getters...
884 - (void) setClassName: (NSString *)name
885 {
886 ASSIGN(_className, name);
887 }
888
889 - (NSString *)className
890 {
891 return _className;
892 }
893
894 - (BOOL)deferFlag
895 {
896 return _deferFlag;
897 }
898
899 - (void)setDeferFlag: (BOOL)flag
900 {
901 _deferFlag = flag;
902 }
903 @end

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26