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