1/* GormCustomView - Visual representation of a custom view placeholder
2 *
3 * Copyright (C) 2001 Free Software Foundation, Inc.
4 *
5 * Author:	Adam Fedor <fedor@gnu.org>
6 * Date:	2001
7 *
8 * This file is part of GNUstep.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
23 */
24
25#include <GormCore/GormCustomView.h>
26#include <GormCore/GormPrivate.h>
27#include <GormCore/GormOpenGLView.h>
28
29#include <AppKit/NSColor.h>
30#include <AppKit/NSGraphics.h>
31#include <AppKit/NSFont.h>
32#include <AppKit/NSNibLoading.h>
33
34#include <GNUstepGUI/GSGormLoading.h>
35#include <GNUstepGUI/GSNibLoading.h>
36
37@class GSCustomView;
38
39@interface CustomView : NSView
40@end
41
42@implementation CustomView
43- (id) initWithFrame: (NSRect)frame
44{
45  if((self = [super initWithFrame: frame]) != nil)
46    {
47      // Replace the CustomView with an NSView of the same dimensions.
48      self = (id)[[NSView alloc] initWithFrame: frame];
49    }
50  return self;
51}
52@end
53
54@implementation GormCustomView
55
56- (id)initWithFrame:(NSRect)frameRect
57{
58  self = [super initWithFrame: frameRect];
59  if(self != nil)
60    {
61      [self setBackgroundColor: [NSColor darkGrayColor]];
62      [self setTextColor: [NSColor whiteColor]];
63      [self setDrawsBackground: YES];
64      [self setAlignment: NSCenterTextAlignment];
65      [self setFont: [NSFont boldSystemFontOfSize: 0]];
66      [self setEditable: NO];
67      [self setSelectable: NO];
68      [self setClassName: @"CustomView"];
69    }
70  return self;
71}
72
73- (void) dealloc
74{
75  RELEASE(className);
76  [super dealloc];
77}
78
79- (NSString*) inspectorClassName
80{
81  return @"GormFilesOwnerInspector";
82}
83
84- (NSString*) classInspectorClassName
85{
86  return @"GormFilesOwnerInspector";
87}
88
89- (void) setClassName: (NSString *)aName
90{
91  ASSIGN(className, aName);
92  [self setStringValue: aName];
93}
94
95- (NSString *) className
96{
97  return className;
98}
99
100- (Class) bestPossibleSuperClass
101{
102  Class cls = [NSView class];
103  GormClassManager *classManager = [(id<Gorm>)NSApp classManager];
104
105  if([classManager isSuperclass: @"NSView" linkedToClass: className])
106    {
107      NSString *superClass = [classManager nonCustomSuperClassOf: className];
108
109      // get the superclass if one exists...
110      if(superClass != nil)
111	{
112	  cls = NSClassFromString(superClass);
113	  if(cls == nil)
114	    {
115	      cls = [NSView class];
116	    }
117	}
118    }
119
120  return cls;
121}
122
123/*
124 * This needs to be coded like a GSNibItem. How do we make sure this
125 * tracks changes in GSNibItem coding?
126 */
127- (void) encodeWithCoder: (NSCoder*)aCoder
128{
129  if([aCoder allowsKeyedCoding])
130    {
131      GormClassManager *classManager = [(id<Gorm>)NSApp classManager];
132      NSString *extension = nil;
133
134      ASSIGNCOPY(extension,[classManager nonCustomSuperClassOf: className]);
135
136      [aCoder encodeObject: className forKey: @"NSClassName"];
137      [aCoder encodeRect: [self frame] forKey: @"NSFrame"];
138
139      if(extension != nil)
140	{
141	  [aCoder encodeObject: extension forKey: @"NSExtension"];
142	}
143
144      if([self nextResponder] != nil)
145	{
146	  [aCoder encodeObject: [self nextResponder] forKey: @"NSNextResponder"];
147	}
148
149      if([self superview] != nil)
150	{
151	  [aCoder encodeObject: [self superview] forKey: @"NSSuperview"];
152	}
153
154      RELEASE(extension);
155    }
156  else
157    {
158      [aCoder encodeObject: [self stringValue]];
159      [aCoder encodeRect: _frame];
160      [aCoder encodeValueOfObjCType: @encode(unsigned int)
161	      at: &_autoresizingMask];
162    }
163}
164
165- (id) initWithCoder: (NSCoder*)aCoder
166{
167  if([aCoder allowsKeyedCoding])
168    {
169      NSCustomView *customView = [[NSCustomView alloc] initWithCoder: aCoder];
170      NSArray *subviews = [customView subviews];
171
172      // if the custom view has subviews....
173      if(subviews != nil && [subviews count] > 0)
174	{
175	  Class cls = [self bestPossibleSuperClass];
176	  id replacementView = [[cls alloc] initWithFrame: [customView frame]];
177	  NSEnumerator *en = [[customView subviews] objectEnumerator];
178	  id v = nil;
179
180	  [replacementView setAutoresizingMask: [customView autoresizingMask]];
181	  while((v = [en nextObject]) != nil)
182	    {
183	      [replacementView addSubview: v];
184	    }
185
186	  return replacementView;
187	}
188      else
189	{
190	  [self initWithFrame: [customView frame]];
191	  _autoresizingMask = [customView autoresizingMask];
192	}
193
194      // get the classname...
195      [self setClassName: [customView className]];
196      // _super_view = [customView superview];
197      // _window = [customView window];
198
199      RELEASE(customView);
200
201      return self;
202    }
203  else
204    {
205      NSInteger version = [aCoder versionForClassName:
206			      NSStringFromClass([GSCustomView class])];
207
208      if (version == 1)
209	{
210	  NSString *string;
211	  // do not decode super. We need to maintain mapping to NibItems
212	  string = [aCoder decodeObject];
213	  _frame = [aCoder decodeRect];
214	  [self initWithFrame: _frame];
215	  [aCoder decodeValueOfObjCType: @encode(unsigned int)
216		  at: &_autoresizingMask];
217	  [self setClassName: string];
218	  return self;
219	}
220      else if (version == 0)
221	{
222	  NSString *string;
223	  // do not decode super. We need to maintain mapping to NibItems
224	  string = [aCoder decodeObject];
225	  _frame = [aCoder decodeRect];
226
227	  [self initWithFrame: _frame];
228	  [self setClassName: string];
229	  return self;
230	}
231      else
232	{
233	  NSLog(@"no initWithCoder for version");
234	  RELEASE(self);
235	  return nil;
236	}
237    }
238  return nil;
239}
240@end
241
242@interface GormTestCustomView : GSNibItem <NSCoding>
243{
244}
245@end
246
247@implementation	GormTestCustomView
248
249- (Class) bestPossibleSuperClass
250{
251  Class cls = [NSView class];
252  GormClassManager *classManager = [(id<Gorm>)NSApp classManager];
253
254  if([classManager isSuperclass: @"NSOpenGLView" linkedToClass: theClass] ||
255     [theClass isEqual: @"NSOpenGLView"])
256    {
257      cls = [GormOpenGLView class];
258    }
259  else  if([classManager isSuperclass: @"NSView" linkedToClass: theClass])
260    {
261      NSString *superClass = [classManager nonCustomSuperClassOf: theClass];
262
263      // get the superclass if one exists...
264      if(superClass != nil)
265	{
266	  cls = NSClassFromString(superClass);
267	  if(cls == nil)
268	    {
269	      cls = [NSView class];
270	    }
271	}
272    }
273
274  return cls;
275}
276
277
278- (id) initWithCoder: (NSCoder*)aCoder
279{
280  id		obj;
281  Class		cls;
282  NSUInteger    mask;
283  GormClassManager *classManager = [(id<Gorm>)NSApp classManager];
284
285  [aCoder decodeValueOfObjCType: @encode(id) at: &theClass];
286  theFrame = [aCoder decodeRect];
287  [aCoder decodeValueOfObjCType: @encode(NSUInteger)
288	  at: &mask];
289
290  cls = NSClassFromString(theClass);
291  if([classManager isSuperclass: @"NSOpenGLView" linkedToClass: theClass] ||
292     [theClass isEqual: @"NSOpenGLView"] || cls == nil)
293    {
294      cls = [self bestPossibleSuperClass];
295    }
296
297  obj = [cls allocWithZone: [self zone]];
298  if (theFrame.size.height > 0 && theFrame.size.width > 0)
299    obj = [obj initWithFrame: theFrame];
300  else
301    obj = [obj init];
302
303  if ([obj respondsToSelector: @selector(setAutoresizingMask:)])
304    {
305      [obj setAutoresizingMask: mask];
306    }
307
308  /*
309  if (![self isKindOfClass: [GSCustomView class]])
310    {
311      RETAIN(obj);
312    }
313  */
314
315  RELEASE(self);
316  return obj;
317}
318
319- (void) encodeWithCoder: (NSCoder *)coder
320{
321  // nothing to do.  This is a class for testing custom views only. GJC
322}
323@end
324
325