/[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.8 - (show annotations) (download)
Sun Sep 28 23:25:16 2003 UTC (20 years, 7 months ago) by gcasa
Branch: MAIN
CVS Tags: gui-0_9_0
Changes since 1.7: +20 -0 lines
Adding fix for report #5205.  Services and Windows menus now should behave correctly.

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

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