1/** <title>GormCustomClassInspector</title> 2 3 <abstract>allow user to select custom classes</abstract> 4 5 Copyright (C) 2002 Free Software Foundation, Inc. 6 Author: Gregory John Casamento <greg_casamento@yahoo.com> 7 Date: September 2002 8 9 This file is part of GNUstep. 10 11 This library is free software; you can redistribute it and/or 12 modify it under the terms of the GNU Library General Public 13 License as published by the Free Software Foundation; either 14 version 3 of the License, or (at your option) any later version. 15 16 This library is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 Library General Public License for more details. 20 21 You should have received a copy of the GNU Library General Public 22 License along with this library; see the file COPYING.LIB. 23 If not, write to the Free Software Foundation, 24 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 25*/ 26 27/* All Rights reserved */ 28 29#include <AppKit/AppKit.h> 30#include "GormCustomClassInspector.h" 31#include "GormPrivate.h" 32#include "GormClassManager.h" 33#include "GormDocument.h" 34#include "GormPrivate.h" 35#include "GormViewEditor.h" 36 37@implementation GormCustomClassInspector 38+ (void) initialize 39{ 40 if (self == [GormCustomClassInspector class]) 41 { 42 // TBD 43 } 44} 45 46- (id) init 47{ 48 self = [super init]; 49 if (self != nil) 50 { 51 // initialize all member variables... 52 _classManager = nil; 53 _currentSelectionClassName = nil; 54 _rowToSelect = 0; 55 56 // load the gui... 57 if (![NSBundle loadNibNamed: @"GormCustomClassInspector" 58 owner: self]) 59 { 60 NSLog(@"Could not open gorm GormCustomClassInspector"); 61 return nil; 62 } 63 } 64 return self; 65} 66 67- (void) _setCurrentSelectionClassName: (id)anobject 68{ 69 NSString *className; 70 71 className = [_classManager customClassForObject: anobject]; 72 if ([className isEqualToString: @""] 73 || className == nil) 74 { 75 className = [anobject className]; 76 } 77 78 ASSIGN(_currentSelectionClassName, className); 79 ASSIGN(_parentClassName, [anobject className]); 80} 81 82- (NSMutableArray *) _generateClassList 83{ 84 NSMutableArray *classes = [NSMutableArray arrayWithObject: _parentClassName]; 85 NSArray *subclasses = [_classManager allSubclassesOf: _parentClassName]; 86 NSEnumerator *en = [subclasses objectEnumerator]; 87 NSString *className = nil; 88 Class parentClass = NSClassFromString(_parentClassName); 89 90 while((className = [en nextObject]) != nil) 91 { 92 if([_classManager isCustomClass: className] == YES) 93 { 94 NSString *superClass = [_classManager nonCustomSuperClassOf: className]; 95 Class cls = NSClassFromString(superClass); 96 if(cls != nil) 97 { 98 if([cls respondsToSelector: @selector(canSubstituteForClass:)]) 99 { 100 if([cls canSubstituteForClass: parentClass]) 101 { 102 [classes addObject: className]; 103 } 104 } 105 } 106 } 107 else if(parentClass != nil) 108 { 109 Class cls = NSClassFromString(className); 110 if(cls != nil) 111 { 112 if([cls respondsToSelector: @selector(canSubstituteForClass:)]) 113 { 114 if([cls canSubstituteForClass: parentClass]) 115 { 116 [classes addObject: className]; 117 } 118 } 119 } 120 } 121 } 122 123 return classes; 124} 125 126- (void) setObject: (id)anObject 127{ 128 if(anObject != nil) 129 { 130 NSMutableArray *classes = nil; 131 132 [super setObject: anObject]; 133 _document = [(id<IB>)NSApp activeDocument]; 134 _classManager = [(id<Gorm>)NSApp classManager]; 135 136 // get the information... 137 NSDebugLog(@"Current selection %@", [self object]); 138 [self _setCurrentSelectionClassName: [self object]]; 139 140 // load the array... 141 [browser loadColumnZero]; 142 143 // get a list of all of the classes allowed and the class to be shown 144 // and select the appropriate row in the inspector... 145 classes = [self _generateClassList]; 146 // [NSMutableArray arrayWithObject: _parentClassName]; 147 // [classes addObjectsFromArray: [_classManager allCustomSubclassesOf: _parentClassName]]; 148 149 _rowToSelect = [classes indexOfObject: _currentSelectionClassName]; 150 _rowToSelect = (_rowToSelect != NSNotFound)?_rowToSelect:0; 151 152 if(_rowToSelect != NSNotFound) 153 { 154 [browser selectRow: _rowToSelect inColumn: 0]; 155 } 156 } 157} 158 159- (void) awakeFromNib 160{ 161 [browser setTarget: self]; 162 [browser setAction: @selector(select:)]; 163 [browser setMaxVisibleColumns: 1]; 164} 165 166- (void) _replaceWithCellClassForClassName: (NSString *)name 167{ 168 NSString *className = name; 169 if([[object class] respondsToSelector: @selector(cellClass)]) 170 { 171 if([_classManager customClassForObject: object]) 172 { 173 if([_classManager isCustomClass: className]) 174 { 175 className = [_classManager nonCustomSuperClassOf: name]; 176 } 177 } 178 179 if(className != nil) 180 { 181 Class cls = NSClassFromString(className); 182 if(cls != nil) 183 { 184 Class cellClass = [cls cellClass]; 185 186 if(cellClass != [[object cell] class]) 187 { 188 id newCell = [[cellClass alloc] init]; 189 id cell = RETAIN([object cell]); // retain the old cell for now... 190 BOOL drawsBackground = NO; 191 192 if([object respondsToSelector: @selector(drawsBackground)]) 193 { 194 drawsBackground = [object drawsBackground]; 195 } 196 197 // TODO: Need to find a more generic way to handle this. Perhaps using 198 // encoding, kv-copying or @defs(...). 199 // set the new cell.. 200 [object setCell: newCell]; 201 202 // general state... 203 if([newCell respondsToSelector: @selector(setFont:)] && 204 [cell respondsToSelector: @selector(font)]) 205 { 206 [newCell setFont: [cell font]]; 207 } 208 if([newCell respondsToSelector: @selector(setEnabled:)] && 209 [cell respondsToSelector: @selector(isEnabled)]) 210 { 211 [newCell setEnabled: [cell isEnabled]]; 212 } 213 if([newCell respondsToSelector: @selector(setEditable:)] && 214 [cell respondsToSelector: @selector(isEditable)]) 215 { 216 [newCell setEditable: [cell isEditable]]; 217 } 218 if([newCell respondsToSelector: @selector(setImportsGraphics:)] && 219 [cell respondsToSelector: @selector(importsGraphics)]) 220 { 221 [newCell setImportsGraphics: [cell importsGraphics]]; 222 } 223 if([newCell respondsToSelector: @selector(setShowsFirstResponder:)] && 224 [cell respondsToSelector: @selector(showsFirstResponder)]) 225 { 226 [newCell setShowsFirstResponder: [cell showsFirstResponder]]; 227 } 228 if([newCell respondsToSelector: @selector(setRefusesFirstResponder:)] && 229 [cell respondsToSelector: @selector(refusesFirstResponder)]) 230 { 231 [newCell setRefusesFirstResponder: [cell refusesFirstResponder]]; 232 } 233 if([newCell respondsToSelector: @selector(setBordered:)] && 234 [cell respondsToSelector: @selector(isBordered)]) 235 { 236 [newCell setBordered: [cell isBordered]]; 237 } 238 if([newCell respondsToSelector: @selector(setBezeled:)] && 239 [cell respondsToSelector: @selector(isBezeled)]) 240 { 241 [newCell setBezeled: [cell isBezeled]]; 242 } 243 if([newCell respondsToSelector: @selector(setScrollable:)] && 244 [cell respondsToSelector: @selector(isScrollable)]) 245 { 246 [newCell setScrollable: [cell isScrollable]]; 247 } 248 if([newCell respondsToSelector: @selector(setSelectable:)] && 249 [cell respondsToSelector: @selector(isSelectable)]) 250 { 251 [newCell setSelectable: [cell isSelectable]]; 252 } 253 if([newCell respondsToSelector: @selector(setState:)] && 254 [cell respondsToSelector: @selector(state)]) 255 { 256 [newCell setState: [cell state]]; 257 } 258 259 if([(NSCell *)cell type] == NSTextCellType) 260 { 261 // title... 262 if([newCell respondsToSelector: @selector(setStringValue:)] && 263 [cell respondsToSelector: @selector(stringValue)]) 264 { 265 [newCell setStringValue: [cell stringValue]]; 266 } 267 if([newCell respondsToSelector: @selector(setTitle:)] && 268 [cell respondsToSelector: @selector(title)]) 269 { 270 [newCell setTitle: [cell title]]; 271 } 272 if([newCell respondsToSelector: @selector(setAlternateTitle:)] && 273 [cell respondsToSelector: @selector(alternateTitle)]) 274 { 275 [newCell setAlternateTitle: [cell alternateTitle]]; 276 } 277 } 278 else if([(NSCell *)cell type] == NSImageCellType) 279 { 280 // images... 281 if([newCell respondsToSelector: @selector(setAlternateImage:)] && 282 [cell respondsToSelector: @selector(alternateImage)]) 283 { 284 [newCell setAlternateImage: [cell alternateImage]]; 285 } 286 if([newCell respondsToSelector: @selector(setImage:)] && 287 [cell respondsToSelector: @selector(image)]) 288 { 289 [newCell setImage: [cell image]]; 290 } 291 if([newCell respondsToSelector: @selector(setImagePosition:)] && 292 [cell respondsToSelector: @selector(imagePosition)]) 293 { 294 [newCell setImagePosition: [cell imagePosition]]; 295 } 296 } 297 // set attributes of textfield. 298 if([object respondsToSelector: @selector(setDrawsBackground:)]) 299 { 300 [object setDrawsBackground: drawsBackground]; 301 } 302 [object setNeedsDisplay: YES]; 303 RELEASE(cell); 304 } 305 } 306 } 307 } 308} 309 310- (void) select: (id)sender 311{ 312 NSCell *cell = [browser selectedCellInColumn: 0]; 313 NSString *stringValue = [NSString stringWithString: [cell stringValue]]; 314 NSString *nameForObject = [_document nameForObject: [self object]]; 315 NSString *classForObject = [[self object] className]; 316 GormViewEditor *gve = (GormViewEditor *)[_document editorForObject: [self object] 317 create: NO]; 318 319 NSDebugLog(@"selected = %@, class = %@",stringValue,nameForObject); 320 321 /* add or remove the mapping as necessary. */ 322 if(nameForObject != nil) 323 { 324 [super ok: sender]; 325 if (![stringValue isEqualToString: classForObject]) 326 { 327 [_classManager setCustomClass: stringValue 328 forName: nameForObject]; 329 } 330 else 331 { 332 [_classManager removeCustomClassForName: nameForObject]; 333 } 334 335 [gve setToolTip: [NSString stringWithFormat: @"%@,%@", 336 nameForObject, 337 stringValue]]; 338 339 [self _replaceWithCellClassForClassName: stringValue]; 340 } 341 else 342 NSLog(@"name for object %@ returned as nil",[self object]); 343} 344 345// Browser delegate 346- (void) browser: (NSBrowser *)sender 347createRowsForColumn: (NSInteger)column 348 inMatrix: (NSMatrix *)matrix 349{ 350 if (_parentClassName != nil) 351 { 352 NSMutableArray *classes; 353 NSEnumerator *e = nil; 354 NSString *class = nil; 355 NSBrowserCell *cell = nil; 356 NSInteger i = 0; 357 358 classes = [self _generateClassList]; 359 // [NSMutableArray arrayWithObject: _parentClassName]; 360 // get a list of all of the classes allowed and the class to be shown. 361 //[classes addObjectsFromArray: 362 // [_classManager allCustomSubclassesOf: _parentClassName]]; 363 364 // enumerate through the classes... 365 e = [classes objectEnumerator]; 366 while ((class = [e nextObject]) != nil) 367 { 368 if ([class isEqualToString: _currentSelectionClassName]) 369 { 370 _rowToSelect = i; 371 } 372 [matrix insertRow: i withCells: nil]; 373 cell = [matrix cellAtRow: i column: 0]; 374 [cell setLeaf: YES]; 375 i++; 376 [cell setStringValue: class]; 377 } 378 } 379} 380 381- (NSString*) browser: (NSBrowser*)sender 382 titleOfColumn: (NSInteger)column 383{ 384 NSDebugLog(@"Delegate called"); 385 return @"Class"; 386} 387 388- (void) browser: (NSBrowser *)sender 389 willDisplayCell: (id)cell 390 atRow: (NSInteger)row 391 column: (NSInteger)column 392{ 393} 394 395- (BOOL) browser: (NSBrowser *)sender 396 isColumnValid: (NSInteger)column 397{ 398 return YES; 399} 400@end 401