From ee2888370c3952f805a4fddaf1fab87486ad43cd Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Tue, 27 Jul 2004 06:20:45 +0000 Subject: [PATCH] Implementation for enhancement req/bug #5024. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/gorm/trunk@19779 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 33 +++++++ Gorm.m | 22 +---- GormDocument.m | 90 +++++++++++++---- GormGenericEditor.m | 6 ++ GormInternalViewEditor.m | 14 +++ GormLib/IBEditors.h | 10 +- GormLib/IBInspector.m | 36 ++++++- GormPrivate.h | 1 + GormViewEditor.h | 2 + GormViewEditor.m | 77 ++++++++++++--- GormViewWindow.h | 33 ++++++- GormViewWindow.m | 120 ++++++++++++++++++----- Palettes/0Menus/GormMenuInspectors.m | 3 +- Palettes/0Menus/GormNSMenu.m | 17 ++-- Palettes/3Containers/GormNSOutlineView.m | 7 ++ Palettes/3Containers/GormNSTableView.m | 7 ++ 16 files changed, 385 insertions(+), 93 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9a8b9f8b..44ba40e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2004-07-27 02:15 Gregory John Casamento + + * Gorm.m: Cleaned up some commented out code. + * GormDocument.m: Added code in [GormDocument instantiateClass] + to add the appropriate information to the document when an + NSView subclass is instantiated in the classes view. + This is for "standalone view" support. Some additional cleanup. + * GormGenericEditor.m: The editor wasn't calling + [GormDocument editor:didCloseForObject:] as it should when the + editor is closed. Added implementation for isOpened to give + any subeditors the correct response when the editor is opened. + * GormInternalViewEditor.m: Added code to show the appropriate + image when we have a standalone view in the document. + * GormPrivate.h: Added declaration for isOpened to + GormGenericEditor class declaration. + * GormViewEditor.h: Added ivar for GormViewWindow. + * GormViewEditor.m: Added code in activate, deactivate, and + resetObject to properly show the standalone view. This allows + the user to see and edit the view. + * GormViewWindow.[hm]: completed implementation of this class + for use by the GormViewEditor. + * GormLib/IBEditors.h: Properly documented resetObject. + * GormLib/IBInspector.m: Added code which releases objects held + by the inspector after the document has been released. This + prevents problems with old objects being retained in memory + by the inspectors until another object is selected. + * Palettes/0Menu/GormNSMenu.m: corrected a crash caused by a + recent change. + * Palettes/3Containers/GormNSOutlineView.m: Added + allocSubstitute method. + * Palettes/3Containers/GormNSTableView.m: Added + allocSubstitute method. + 2004-07-20 20:04 Gregory John Casamento * GormDocument.m: Leak fixes and general clean up. diff --git a/Gorm.m b/Gorm.m index 85ddb444..2bf51500 100644 --- a/Gorm.m +++ b/Gorm.m @@ -930,18 +930,13 @@ NSString *GormResizeCellNotification = @"GormResizeCellNotification"; [(GormGenericEditor *)selectionOwner ungroup]; } - - -/***********************************************************************/ -/*********************** Classes Action *******************************/ -/***********************************************************************/ +/// Classes actions... - (void) createSubclass: (id)sender { [(GormDocument *)[self activeDocument] createSubclass: sender]; } - - (void) loadClass: (id)sender { // Call the current document and create the class @@ -969,18 +964,7 @@ NSString *GormResizeCellNotification = @"GormResizeCellNotification"; [(GormDocument *)[self activeDocument] remove: sender]; } -/* -- (id) editClass: (id)sender -{ - [self inspector: self]; - return [(id)[self activeDocument] editClass: sender]; -} -*/ - - -/***********************************************************************/ -/*********************** Classes Action *******************************/ -/***********************************************************************/ +/// Palettes Actions... - (void) inspector: (id) sender { @@ -997,6 +981,8 @@ NSString *GormResizeCellNotification = @"GormResizeCellNotification"; [[self palettesManager] openPalette: sender]; } +/// Testing methods... + - (void) deferredEndTesting: (id) sender { [[NSRunLoop currentRunLoop] diff --git a/GormDocument.m b/GormDocument.m index cc419e76..f789bc8f 100644 --- a/GormDocument.m +++ b/GormDocument.m @@ -30,6 +30,7 @@ #include "GormOutlineView.h" #include "GormFunctions.h" #include "GormFilePrefsManager.h" +#include "GormViewWindow.h" #include #include #include @@ -38,7 +39,7 @@ #include -@interface GormDisplayCell : NSButtonCell +@interface GormDisplayCell : NSButtonCell @end @implementation GormDisplayCell @@ -1437,11 +1438,10 @@ static NSImage *fileImage = nil; ofClass: [GormObjectToEditor class]]; if ([links count] == 0 && flag == YES) { - Class eClass; + Class eClass = NSClassFromString([anObject editorClassName]); id editor; id link; - eClass = NSClassFromString([anObject editorClassName]); editor = [[eClass alloc] initWithObject: anObject inDocument: self]; link = [GormObjectToEditor new]; [link setSource: anObject]; @@ -1726,15 +1726,67 @@ static NSImage *fileImage = nil; { if([object isEqualToString: @"FirstResponder"]) return nil; - - item = [[GormObjectProxy alloc] initWithClassName: object - frame: NSMakeRect(0,0,0,0)]; - - [self setName: nil forObject: item]; - [self attachObject: item toParent: nil]; - - // [selectionView selectCellWithTag: 0]; - [selectionBox setContentView: scrollView]; + + if([classManager isSuperclass: @"NSView" linkedToClass: object]) + { + Class cls; + NSString *className = object; + BOOL isCustom = [classManager isCustomClass: object]; + id instance; + + if(isCustom) + { + className = [classManager nonCustomSuperClassOf: object]; + } + + // instantiate the object or it's substitute... + cls = NSClassFromString(className); + if([cls respondsToSelector: @selector(allocSubstitute)]) + { + instance = [cls allocSubstitute]; + } + else + { + instance = [cls alloc]; + } + + // give it some initial dimensions... + if([instance respondsToSelector: @selector(initWithFrame:)]) + { + instance = [instance initWithFrame: NSMakeRect(10,10,380,280)]; + } + else + { + instance = [instance init]; + } + + // add it to the top level objects... + [self setName: nil forObject: instance]; + [self attachObject: instance toParent: nil]; + [topLevelObjects addObject: instance]; + [objectsView addObject: instance]; + + // we want to record if it's custom or not and act appropriately... + if(isCustom) + { + NSString *name = [self nameForObject: instance]; + [classManager setCustomClass: object + forObject: name]; + } + + [selectionBox setContentView: scrollView]; + NSLog(@"Instantiate NSView subclass %@",object); + } + else + { + item = [[GormObjectProxy alloc] initWithClassName: object + frame: NSMakeRect(0,0,0,0)]; + + [self setName: nil forObject: item]; + [self attachObject: item toParent: nil]; + + [selectionBox setContentView: scrollView]; + } } } @@ -2530,7 +2582,7 @@ static NSImage *fileImage = nil; NSString *oldName; NSMutableDictionary *cc = [classManager customClassMap]; NSString *className; - NSString *nameCopy; + // NSString *nameCopy; if (object == nil) { @@ -2591,15 +2643,15 @@ static NSImage *fileImage = nil; { return; /* Already have this name ... nothing to do */ } - RETAIN(object); // the next operation will attempt to release the object, we need to retain it. + // RETAIN(object); // the next operation will attempt to release the object, we need to retain it. [nameTable removeObjectForKey: oldName]; NSMapRemove(objToName, (void*)object); } } - nameCopy = [aName copy]; /* Make sure it's immutable */ - [nameTable setObject: object forKey: nameCopy]; + // nameCopy = [aName copy]; /* Make sure it's immutable */ + [nameTable setObject: object forKey: aName]; RELEASE(object); // make sure that when it's removed from the table, it's released. - NSMapInsert(objToName, (void*)object, (void*)nameCopy); + NSMapInsert(objToName, (void*)object, (void*) aName); //nameCopy); if (oldName != nil) { [nameTable removeObjectForKey: oldName]; @@ -2617,10 +2669,10 @@ static NSImage *fileImage = nil; if(className != nil) { [cc removeObjectForKey: oldName]; - [cc setObject: className forKey: nameCopy]; + [cc setObject: className forKey: aName]; //nameCopy]; } } - RELEASE(nameCopy); // release the copy of the name which we made... + // RELEASE(nameCopy); // release the copy of the name which we made... } - (void) setObject: (id)anObject isVisibleAtLaunch: (BOOL)flag diff --git a/GormGenericEditor.m b/GormGenericEditor.m index c6337e34..a66832f8 100644 --- a/GormGenericEditor.m +++ b/GormGenericEditor.m @@ -89,6 +89,7 @@ - (void) close { closed = YES; + [document editor: self didCloseForObject: [self editedObject]]; [self deactivate]; [self closeSubeditors]; } @@ -309,4 +310,9 @@ { return objects; } + +- (BOOL) isOpened +{ + return (closed == NO); +} @end diff --git a/GormInternalViewEditor.m b/GormInternalViewEditor.m index 788e3a98..a0fa0854 100644 --- a/GormInternalViewEditor.m +++ b/GormInternalViewEditor.m @@ -62,6 +62,20 @@ static NSImage *horizontalImage; return @"GormViewEditor"; } } + +- (NSImage*) imageForViewer +{ + static NSImage *image = nil; + + if (image == nil) + { + NSBundle *bundle = [NSBundle mainBundle]; + NSString *path = [bundle pathForImageResource: @"GormView"]; + image = [[NSImage alloc] initWithContentsOfFile: path]; + } + + return image; +} @end diff --git a/GormLib/IBEditors.h b/GormLib/IBEditors.h index ff92af9f..7e04d14d 100644 --- a/GormLib/IBEditors.h +++ b/GormLib/IBEditors.h @@ -132,21 +132,19 @@ extern NSString *IBClassNameChangedNotification; */ // - (void) pasteInSelection; -/* - * FIXME - I don't think we use this. +/** + * Redraws the edited object */ - (void) resetObject: (id)anObject; - - -/* +/** * When an editor resigns the selection ownership, all editors are asked if * they want selection ownership, and the first one to return YES gets made * into the current selection owner. */ - (BOOL) wantsSelection; -/* +/** * This returns the window in which the editor is drawn. */ - (NSWindow*) window; diff --git a/GormLib/IBInspector.m b/GormLib/IBInspector.m index e5796d5d..3272aa84 100644 --- a/GormLib/IBInspector.m +++ b/GormLib/IBInspector.m @@ -23,19 +23,52 @@ */ #include +#include #include #include #include +static NSNotificationCenter *nc = nil; + @implementation IBInspector ++ (void) initialize +{ + if(self == [IBInspector class]) + { + nc = [NSNotificationCenter defaultCenter]; + } +} + +- (id) init +{ + if((self = [super init]) != nil) + { + [nc addObserver: self + selector: @selector(handleNotification:) + name: IBWillCloseDocumentNotification + object: nil]; + } + + return self; +} + - (void) dealloc { - [[NSNotificationCenter defaultCenter] removeObserver: self]; + [nc removeObserver: self]; RELEASE(object); [super dealloc]; } +- (void) handleNotification: (NSNotification *)notification +{ + id doc = [notification object]; + if([doc nameForObject: object] != nil) + { + [self setObject: nil]; + } +} + - (NSView*) initialFirstResponder { return nil; @@ -88,4 +121,3 @@ return window; } @end - diff --git a/GormPrivate.h b/GormPrivate.h index 11839bea..09b9fc37 100644 --- a/GormPrivate.h +++ b/GormPrivate.h @@ -206,6 +206,7 @@ extern NSString *GormResizeCellNotification; - (NSRect) rectForObject: (id)anObject; - (NSArray *) objects; +- (BOOL) isOpened; @end // private methods... diff --git a/GormViewEditor.h b/GormViewEditor.h index 62008e0b..14093851 100644 --- a/GormViewEditor.h +++ b/GormViewEditor.h @@ -29,6 +29,7 @@ @class GormViewWithSubviewsEditor; @class GormPlacementInfo; +@class GormViewWindow; @interface GormViewEditor : NSView { @@ -37,6 +38,7 @@ BOOL activated; BOOL closed; GormViewWithSubviewsEditor *parent; + GormViewWindow *viewWindow; } - (BOOL) activate; - (id) initWithObject: (id)anObject diff --git a/GormViewEditor.m b/GormViewEditor.m index 37a50615..c42deb3f 100644 --- a/GormViewEditor.m +++ b/GormViewEditor.m @@ -30,18 +30,14 @@ #include "GormViewWithSubviewsEditor.h" #include "GormPlacementInfo.h" #include "GormFunctions.h" +#include "GormViewWindow.h" #include #include - - - @implementation GormPlacementInfo @end - - @implementation GormPlacementHint - (float) position { return _position; } - (float) start { return _start; } @@ -140,7 +136,7 @@ static BOOL currently_displaying = NO; - (void) encodeWithCoder: (NSCoder*)aCoder { [NSException raise: NSInternalInconsistencyException - format: @"Argh - encoding view editor"]; + format: @"Cannot encode a GormViewEditor"]; } - (id) document @@ -159,7 +155,22 @@ static BOOL currently_displaying = NO; { if (activated == NO) { - NSView *superview = [_editedObject superview]; + NSView *superview; + + // put the view into a "view window" if it's a standalone view... + if([_editedObject window] == nil) + { + if(viewWindow == nil) + { + viewWindow = [[GormViewWindow alloc] initWithView: _editedObject]; + } + else + { + [viewWindow setView: _editedObject]; + } + } + + superview = [_editedObject superview]; [self setFrame: [_editedObject frame]]; [self setBounds: [self frame]]; @@ -168,8 +179,16 @@ static BOOL currently_displaying = NO; with: self]; [self setAutoresizingMask: NSViewMaxXMargin | NSViewMinYMargin]; - [self setAutoresizesSubviews: NO]; - + // we want autoresizing for standalone views... + if(viewWindow == nil) + { + [self setAutoresizesSubviews: NO]; + } + else + { + [self setAutoresizesSubviews: YES]; + } + [self addSubview: _editedObject]; [_editedObject setPostsFrameChangedNotifications: YES]; @@ -187,13 +206,18 @@ static BOOL currently_displaying = NO; object: self]; parent = (GormViewWithSubviewsEditor *)[document parentEditorForEditor: self]; - if ([parent isKindOfClass: [GormViewEditor class]]) - [parent setNeedsDisplay: YES]; + { + [parent setNeedsDisplay: YES]; + } else - [self setNeedsDisplay: YES]; + { + [self setNeedsDisplay: YES]; + } + activated = YES; - return YES; + + return activated; } return NO; @@ -216,7 +240,12 @@ static BOOL currently_displaying = NO; if (closed == NO) { [self deactivate]; - + + if(viewWindow != nil) + { + [viewWindow close]; + } + [document editor: self didCloseForObject: _editedObject]; closed = YES; } @@ -238,6 +267,13 @@ static BOOL currently_displaying = NO; [[NSNotificationCenter defaultCenter] removeObserver: self]; + // make sure the view isn't in the window after deactivation. + if(viewWindow != nil) + { + [_editedObject removeFromSuperview]; // WithoutNeedingDisplay]; + [viewWindow orderOut: self]; + } + activated = NO; } } @@ -1236,7 +1272,12 @@ static BOOL currently_displaying = NO; { if (parent) { - [parent mouseDown: theEvent]; + // TODO: We should find a better test than this, but it will do + // for now... + if([parent isKindOfClass: [GormGenericEditor class]] == NO) + { + [parent mouseDown: theEvent]; + } } else return [self noResponderFor: @selector(mouseDown:)]; @@ -1316,7 +1357,11 @@ static BOOL currently_displaying = NO; - (void) resetObject: (id)anObject { - NSLog(@"resetObject should not be called on GormViewEditor !"); + /// NSLog(@"resetObject should not be called on GormViewEditor !"); + if(viewWindow != nil) + { + [viewWindow orderFront: self]; + } } - (void) orderFront diff --git a/GormViewWindow.h b/GormViewWindow.h index 7daaec7e..5327be69 100644 --- a/GormViewWindow.h +++ b/GormViewWindow.h @@ -1,3 +1,30 @@ +/* GormViewWindow.h + * + * Copyright (C) 2004 Free Software Foundation, Inc. + * + * Author: Gregory John Casamento + * Date: 2004 + * + * This file is part of GNUstep. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef INCLUDED_GormViewWindow_h +#define INCLUDED_GormViewWindow_h + #include #include @@ -6,6 +33,8 @@ NSView *_view; } - (id) initWithView: (NSView *)view; -- (void) setView: (NSView *) view; -- (NSView *)view; +- (NSView *)view; +- (void) setView: (NSView *)view; @end + +#endif diff --git a/GormViewWindow.m b/GormViewWindow.m index 09064b87..b48cfd04 100644 --- a/GormViewWindow.m +++ b/GormViewWindow.m @@ -1,39 +1,110 @@ +/* GormViewWindow.m + * + * Copyright (C) 2004 Free Software Foundation, Inc. + * + * Author: Gregory John Casamento + * Date: 2004 + * + * This file is part of GNUstep. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + #include "GormViewWindow.h" #include #include +#include #include +#include +#include -@implementation GormViewWindow -- (id) initWithView: (NSView *)view +@interface GormViewWindowDelegate : NSObject +{ + id _view; +} + +- (id) initWithView: (id)view; +- (void) resize; +@end + +@implementation GormViewWindowDelegate + +- (id) initWithView: (id)view; { - // initializer yourself.... if((self = [super init]) != nil) { - ASSIGN(_view,view); - [self setDelegate: self]; - } + _view = view; + [self resize]; + } return self; } -- (void) _resizeView +- (void) resize { - NSRect newFrame = [[self contentView] frame]; - newFrame.origin.x += 10; - newFrame.origin.y += 10; - newFrame.size.height -= 10; - newFrame.size.width -= 10; + NSWindow *window = [_view window]; + NSRect newFrame = [window frame]; + + newFrame.origin.x = 10; + newFrame.origin.y = 20; + newFrame.size.height -= 70; + newFrame.size.width -= 20; [_view setFrame: newFrame]; + + NSLog(@"Resized %@",NSStringFromRect(newFrame)); } -- (void) setView: (NSView *) view +- (void) windowDidResize: (NSNotification *)notification +{ + [self resize]; +} + +@end + + +@implementation GormViewWindow + +- (id) initWithView: (NSView *)view +{ + if((self = [super init]) != nil) + { + NSString *className = NSStringFromClass([view class]); + NSString *objectName = [[(id)NSApp activeDocument] nameForObject: view]; + NSString *title = [NSString stringWithFormat: @"View Window: (%@, %@)", + className, objectName]; + + [self setTitle: title]; + [self setFrame: NSMakeRect(0,0,400,300) display: YES]; + // [self setBackgroundColor: [NSColor redColor]]; + [self setView: view]; + } + return self; +} + +- (void) setView: (NSView *)view { if(_view != nil) { - [_view removeFromSuperview]; + [_view removeFromSuperviewWithoutNeedingDisplay]; } - ASSIGN(_view,view); - [self _resizeView]; + + _view = view; + [[self contentView] addSubview: _view]; + DESTROY(_delegate); + [self setDelegate: [[GormViewWindowDelegate alloc] initWithView: _view]]; + [self center]; } - (NSView *) view @@ -41,12 +112,17 @@ return _view; } -- (void) windowDidResize: (NSNotification *)notification +- (void) encodeWithCoder: (NSCoder *)coder { - if(_view != nil) - { - [self _resizeView]; - } + [NSException raise: NSInternalInconsistencyException + format: @"Cannot encode a GormViewWindow"]; } + +- (void) dealloc +{ + DESTROY(_delegate); + [super dealloc]; +} + @end - + diff --git a/Palettes/0Menus/GormMenuInspectors.m b/Palettes/0Menus/GormMenuInspectors.m index 26702e26..05ddae8f 100644 --- a/Palettes/0Menus/GormMenuInspectors.m +++ b/Palettes/0Menus/GormMenuInspectors.m @@ -62,9 +62,8 @@ - (void) setObject: (id)anObject { GormDocument *doc = (GormDocument *)[(id)NSApp activeDocument]; - // BOOL flag = NO; - object = nil; // remove reference to old object... + ASSIGN(object, nil); // remove reference to old object... [super setObject: anObject]; [titleText setStringValue: [object title]]; [autoenable setState: ([object autoenablesItems]?NSOnState:NSOffState)]; diff --git a/Palettes/0Menus/GormNSMenu.m b/Palettes/0Menus/GormNSMenu.m index 9ec8e6d8..864a9fcf 100644 --- a/Palettes/0Menus/GormNSMenu.m +++ b/Palettes/0Menus/GormNSMenu.m @@ -25,6 +25,7 @@ #include "GormNSMenu.h" // this must be done here, since Gorm must access this variable.. +/* @interface NSResponder (GormNSMenuPrivate) - (NSMenu *) _menu; - (void) _setMenu: (NSMenu *)m; @@ -41,8 +42,9 @@ _menu = m; } @end +*/ -@interface GormNSMenuWindow : NSWindow // NSPanel +@interface GormNSMenuWindow : NSWindow { GormDocument *_document; } @@ -58,10 +60,12 @@ return YES; } +/* - (void)setMenu: (NSMenu*)menu; { [self _setMenu: menu]; } +*/ - (void)setDocument: (GormDocument *)document { @@ -71,11 +75,11 @@ - (void)resignMainWindow { [super resignMainWindow]; - if ([[self _menu] _ownedByPopUp]) + if ([[self menu] _ownedByPopUp]) { [[NSRunLoop currentRunLoop] performSelector: @selector(close) - target: [self _menu] + target: [self menu] argument: nil order: 500000 modes: [NSArray arrayWithObjects: NSDefaultRunLoopMode, @@ -88,7 +92,7 @@ - (void)becomeMainWindow { [super becomeMainWindow]; - if ([[self _menu] _ownedByPopUp] ) + if ([[self menu] _ownedByPopUp] ) { // do nothing... } @@ -111,8 +115,8 @@ - (void) dealloc { - // FIXME: This prevents a leak and a crash. - [self _setMenu: nil]; + [self setMenu: nil]; + [super dealloc]; } @end @@ -133,6 +137,7 @@ [win setMenu: self]; [win setLevel: NSSubmenuWindowLevel]; [win setExcludedFromWindowsMenu: YES]; + RETAIN(win); // FIXME: Argh.. this may leak.. temporary fix. return win; } diff --git a/Palettes/3Containers/GormNSOutlineView.m b/Palettes/3Containers/GormNSOutlineView.m index ff695a42..d0ab3bb3 100644 --- a/Palettes/3Containers/GormNSOutlineView.m +++ b/Palettes/3Containers/GormNSOutlineView.m @@ -169,6 +169,13 @@ static id _sharedDataSource = nil; +@implementation NSOutlineView (GormPrivate) ++ (id) allocSubstitute +{ + return [GormNSOutlineView alloc]; +} +@end + @implementation GormNSOutlineView + (id) sharedDataSource { diff --git a/Palettes/3Containers/GormNSTableView.m b/Palettes/3Containers/GormNSTableView.m index 5263f049..3656dba0 100644 --- a/Palettes/3Containers/GormNSTableView.m +++ b/Palettes/3Containers/GormNSTableView.m @@ -80,6 +80,13 @@ objectValueForTableColumn:(NSTableColumn *)aTableColumn static id _sharedDataSource = nil; +@implementation NSTableView (GormPrivate) ++ (id) allocSubstitute +{ + return [GormNSTableView alloc]; +} +@end + @implementation GormNSTableView + (id) sharedDataSource {