1999-12-23 11:14:20 +00:00
|
|
|
/* GormObjectInspector.m
|
|
|
|
*
|
|
|
|
* Copyright (C) 1999 Free Software Foundation, Inc.
|
|
|
|
*
|
|
|
|
* Author: Richard Frith-Macdonald <richard@brainstrom.co.uk>
|
|
|
|
* Date: 1999
|
|
|
|
*
|
|
|
|
* 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
|
2007-11-05 23:44:36 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1999-12-23 11:14:20 +00:00
|
|
|
* (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
|
2005-05-26 03:37:38 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
1999-12-23 11:14:20 +00:00
|
|
|
*/
|
|
|
|
|
2005-08-08 01:07:35 +00:00
|
|
|
#include "GormObjectInspector.h"
|
1999-12-23 16:36:51 +00:00
|
|
|
|
2005-08-08 01:07:35 +00:00
|
|
|
@implementation GormObjectInspector
|
1999-12-23 16:36:51 +00:00
|
|
|
|
2005-08-08 01:07:35 +00:00
|
|
|
- (id) init
|
1999-12-23 11:14:20 +00:00
|
|
|
{
|
2005-08-08 01:07:35 +00:00
|
|
|
self = [super init];
|
|
|
|
if (self != nil)
|
|
|
|
{
|
2023-06-14 07:40:51 +00:00
|
|
|
NSBundle *bundle = [NSBundle bundleForClass: [self class]];
|
|
|
|
|
2023-10-22 18:39:24 +00:00
|
|
|
if([bundle loadNibNamed: @"GormObjectInspector" owner: self topLevelObjects: NULL] == NO)
|
2005-08-08 01:07:35 +00:00
|
|
|
{
|
|
|
|
NSLog(@"Couldn't load GormObjectInsector");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2023-06-14 07:40:51 +00:00
|
|
|
sets = [[NSMutableArray alloc] init];
|
|
|
|
gets = [[NSMutableDictionary alloc] init];
|
|
|
|
types = [[NSMutableDictionary alloc] init];
|
|
|
|
|
|
|
|
okButton = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,90,20)];
|
|
|
|
[okButton setAutoresizingMask: NSViewMaxYMargin | NSViewMinXMargin];
|
|
|
|
[okButton setAction: @selector(ok:)];
|
|
|
|
[okButton setTarget: self];
|
|
|
|
[okButton setTitle: _(@"OK")];
|
|
|
|
[okButton setEnabled: NO];
|
|
|
|
|
|
|
|
revertButton = nil;
|
2005-08-08 01:07:35 +00:00
|
|
|
}
|
|
|
|
return self;
|
1999-12-23 11:14:20 +00:00
|
|
|
}
|
|
|
|
|
2013-01-30 12:43:27 +00:00
|
|
|
- (NSInteger) browser: (NSBrowser*)sender numberOfRowsInColumn: (NSInteger)column
|
1999-12-23 11:14:20 +00:00
|
|
|
{
|
1999-12-23 16:36:51 +00:00
|
|
|
return [sets count];
|
1999-12-23 11:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) browser: (NSBrowser*)sender
|
|
|
|
selectCellWithString: (NSString*)title
|
2013-01-30 12:43:27 +00:00
|
|
|
inColumn: (NSInteger)col
|
1999-12-23 11:14:20 +00:00
|
|
|
{
|
2005-08-08 01:07:35 +00:00
|
|
|
[self update: self];
|
1999-12-23 11:14:20 +00:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2013-01-30 12:43:27 +00:00
|
|
|
- (NSString*) browser: (NSBrowser*)sender titleOfColumn: (NSInteger)col
|
1999-12-23 11:14:20 +00:00
|
|
|
{
|
|
|
|
return @"Attribute setters";
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) browser: (NSBrowser*)sender
|
|
|
|
willDisplayCell: (id)aCell
|
2013-01-30 12:43:27 +00:00
|
|
|
atRow: (NSInteger)row
|
|
|
|
column: (NSInteger)col
|
1999-12-23 11:14:20 +00:00
|
|
|
{
|
1999-12-23 16:36:51 +00:00
|
|
|
if (row >= 0 && row < [sets count])
|
1999-12-23 11:14:20 +00:00
|
|
|
{
|
1999-12-23 16:36:51 +00:00
|
|
|
[aCell setStringValue: [sets objectAtIndex: row]];
|
1999-12-23 11:14:20 +00:00
|
|
|
[aCell setEnabled: YES];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[aCell setStringValue: @""];
|
|
|
|
[aCell setEnabled: NO];
|
|
|
|
}
|
|
|
|
[aCell setLeaf: YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
1999-12-23 16:36:51 +00:00
|
|
|
RELEASE(gets);
|
|
|
|
RELEASE(sets);
|
1999-12-23 11:14:20 +00:00
|
|
|
RELEASE(types);
|
|
|
|
RELEASE(okButton);
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) ok: (id)sender
|
|
|
|
{
|
1999-12-23 16:36:51 +00:00
|
|
|
NSString *name = [[browser selectedCell] stringValue];
|
2012-04-20 06:12:32 +00:00
|
|
|
NSUInteger pos;
|
1999-12-23 16:36:51 +00:00
|
|
|
|
|
|
|
if (name == nil || (pos = [sets indexOfObject: name]) == NSNotFound)
|
|
|
|
{
|
2003-05-24 12:40:54 +00:00
|
|
|
[label setTitle: _(@"No Type")];
|
1999-12-23 16:36:51 +00:00
|
|
|
[value setStringValue: @""];
|
|
|
|
[okButton setEnabled: NO];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SEL set = NSSelectorFromString(name);
|
|
|
|
NSString *type = [types objectForKey: name];
|
2005-01-28 05:41:55 +00:00
|
|
|
|
|
|
|
[super ok: sender];
|
1999-12-23 16:36:51 +00:00
|
|
|
if (type == typeChar)
|
|
|
|
{
|
|
|
|
char v = [value intValue];
|
|
|
|
void (*imp)(id,SEL,char);
|
|
|
|
|
|
|
|
imp = (void (*)(id,SEL,char))[object methodForSelector: set];
|
|
|
|
(*imp)(object, set, v);
|
|
|
|
}
|
|
|
|
else if (type == typeUChar)
|
|
|
|
{
|
|
|
|
unsigned char v = [value intValue];
|
|
|
|
void (*imp)(id,SEL,unsigned char);
|
|
|
|
|
|
|
|
imp = (void (*)(id,SEL,unsigned char))[object methodForSelector: set];
|
|
|
|
(*imp)(object, set, v);
|
|
|
|
}
|
|
|
|
else if (type == typeInt)
|
|
|
|
{
|
|
|
|
int v = [value intValue];
|
|
|
|
void (*imp)(id,SEL,int);
|
|
|
|
|
|
|
|
imp = (void (*)(id,SEL,int))[object methodForSelector: set];
|
|
|
|
(*imp)(object, set, v);
|
|
|
|
}
|
|
|
|
else if (type == typeUInt)
|
|
|
|
{
|
|
|
|
unsigned int v = [value intValue];
|
|
|
|
void (*imp)(id,SEL,unsigned int);
|
|
|
|
|
|
|
|
imp = (void (*)(id,SEL,unsigned int))[object methodForSelector: set];
|
|
|
|
(*imp)(object, set, v);
|
|
|
|
}
|
|
|
|
else if (type == typeFloat)
|
|
|
|
{
|
|
|
|
float v = [value floatValue];
|
|
|
|
void (*imp)(id,SEL,float);
|
|
|
|
|
|
|
|
imp = (void (*)(id,SEL,float))[object methodForSelector: set];
|
|
|
|
(*imp)(object, set, v);
|
|
|
|
}
|
|
|
|
else if (type == typeDouble)
|
|
|
|
{
|
|
|
|
float v = [value doubleValue];
|
|
|
|
void (*imp)(id,SEL,double);
|
|
|
|
|
|
|
|
imp = (void (*)(id,SEL,double))[object methodForSelector: set];
|
|
|
|
(*imp)(object, set, v);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
id v = [value stringValue];
|
|
|
|
IMP imp = [object methodForSelector: set];
|
|
|
|
|
|
|
|
if (isString == YES)
|
|
|
|
{
|
|
|
|
(*imp)(object, set, v);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
|
|
|
|
v = [v stringByTrimmingSpaces];
|
2003-05-24 12:40:54 +00:00
|
|
|
result = NSRunAlertPanel(_(@"Settings"),
|
|
|
|
[NSString stringWithFormat: _(@"Set object using '%@' as"), v],
|
|
|
|
_(@"Object name"),_( @"String"), _(@"Class name"));
|
1999-12-23 16:36:51 +00:00
|
|
|
if (result == NSAlertAlternateReturn)
|
|
|
|
{
|
|
|
|
(*imp)(object, set, v);
|
|
|
|
}
|
|
|
|
else if (result == NSAlertOtherReturn)
|
|
|
|
{
|
|
|
|
Class c = NSClassFromString(v);
|
|
|
|
|
|
|
|
if (c != 0)
|
|
|
|
{
|
2005-06-17 04:41:24 +00:00
|
|
|
(*imp)(object, set, [[c alloc] init]);
|
1999-12-23 16:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-06-17 16:14:48 +00:00
|
|
|
id o = [[(id<IB>)[NSApp delegate] activeDocument] objectForName: v];
|
1999-12-23 16:36:51 +00:00
|
|
|
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
(*imp)(object, set, o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-08-08 01:07:35 +00:00
|
|
|
[self update: self];
|
1999-12-23 16:36:51 +00:00
|
|
|
}
|
1999-12-23 11:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setObject: (id)anObject
|
|
|
|
{
|
|
|
|
if (anObject != nil && anObject != object)
|
|
|
|
{
|
1999-12-23 16:36:51 +00:00
|
|
|
Class c = [anObject class];
|
|
|
|
|
1999-12-23 11:14:20 +00:00
|
|
|
ASSIGN(object, anObject);
|
1999-12-23 16:36:51 +00:00
|
|
|
[sets removeAllObjects];
|
|
|
|
[gets removeAllObjects];
|
|
|
|
[types removeAllObjects];
|
1999-12-23 11:14:20 +00:00
|
|
|
|
1999-12-23 16:36:51 +00:00
|
|
|
while (c != nil && c != [NSObject class])
|
|
|
|
{
|
2010-09-16 05:04:00 +00:00
|
|
|
unsigned int count;
|
|
|
|
Method *methods = class_copyMethodList(c, &count);
|
1999-12-23 16:36:51 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2010-09-16 05:04:00 +00:00
|
|
|
SEL sSel = method_getName(methods[i]);
|
1999-12-23 16:36:51 +00:00
|
|
|
NSString *set = NSStringFromSelector(sSel);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We are interested in methods that set values - they have
|
|
|
|
* a 'set' prefic and a colon as the last character.
|
|
|
|
* we ignore duplicates from superclasses.
|
|
|
|
*/
|
|
|
|
if ([set hasPrefix: @"set"] == YES
|
|
|
|
&& [set rangeOfString: @":"].location == [set length] - 1
|
|
|
|
&& [sets containsObject: set] == NO)
|
|
|
|
{
|
|
|
|
char tmp[[set cStringLength]+1];
|
2010-09-16 05:04:00 +00:00
|
|
|
const char *tInfo = method_getTypeEncoding(methods[i]);
|
1999-12-23 16:36:51 +00:00
|
|
|
NSString *type = nil;
|
|
|
|
NSString *get;
|
|
|
|
SEL gSel;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* see if we can find an appropriate method to get the
|
|
|
|
* current value for an attribute we want to set.
|
|
|
|
*/
|
|
|
|
[set getCString: tmp];
|
|
|
|
tmp[3] = tolower(tmp[3]);
|
|
|
|
tmp[strlen(tmp)-1] = '\0';
|
|
|
|
get = [NSString stringWithCString: &tmp[3]];
|
|
|
|
gSel = NSSelectorFromString(get);
|
|
|
|
if (gSel == 0 || [object respondsToSelector: gSel] == NO)
|
|
|
|
{
|
|
|
|
get = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip the return type and the receiver and
|
|
|
|
* selector specifications to the first (only) arg.
|
|
|
|
*/
|
|
|
|
tInfo = objc_skip_typespec(tInfo);
|
|
|
|
if (*tInfo == '+')
|
|
|
|
{
|
|
|
|
tInfo++;
|
|
|
|
}
|
|
|
|
while (isdigit(*tInfo))
|
|
|
|
{
|
|
|
|
tInfo++;
|
|
|
|
}
|
|
|
|
tInfo = objc_skip_argspec(tInfo);
|
|
|
|
tInfo = objc_skip_argspec(tInfo);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now find arguments whose types we can reasonably
|
|
|
|
* deal with.
|
|
|
|
*/
|
|
|
|
switch (*tInfo)
|
|
|
|
{
|
|
|
|
case _C_ID:
|
|
|
|
type = typeId;
|
|
|
|
break;
|
|
|
|
case _C_CHR:
|
|
|
|
type = typeChar;
|
|
|
|
break;
|
|
|
|
case _C_UCHR:
|
|
|
|
type = typeUChar;
|
|
|
|
break;
|
|
|
|
case _C_INT:
|
|
|
|
type = typeInt;
|
|
|
|
break;
|
|
|
|
case _C_UINT:
|
|
|
|
type = typeUInt;
|
|
|
|
break;
|
|
|
|
case _C_FLT:
|
|
|
|
type = typeFloat;
|
|
|
|
break;
|
|
|
|
case _C_DBL:
|
|
|
|
type = typeDouble;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
type = nil;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (type != nil)
|
|
|
|
{
|
|
|
|
[sets addObject: set];
|
|
|
|
if (get != nil)
|
|
|
|
{
|
|
|
|
[gets setObject: get forKey: set];
|
|
|
|
}
|
|
|
|
[types setObject: type forKey: set];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-09-16 05:04:00 +00:00
|
|
|
free(methods);
|
1999-12-23 16:36:51 +00:00
|
|
|
c = [c superclass];
|
|
|
|
}
|
|
|
|
[sets sortUsingSelector: @selector(compare:)];
|
1999-12-23 11:14:20 +00:00
|
|
|
[browser loadColumnZero];
|
2005-08-08 01:07:35 +00:00
|
|
|
[self update: self];
|
1999-12-23 11:14:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-08 01:07:35 +00:00
|
|
|
- (void) update: (id)sender
|
1999-12-23 11:14:20 +00:00
|
|
|
{
|
1999-12-23 16:36:51 +00:00
|
|
|
NSString *name = [[browser selectedCell] stringValue];
|
2012-04-20 06:12:32 +00:00
|
|
|
NSUInteger pos;
|
1999-12-23 16:36:51 +00:00
|
|
|
|
|
|
|
isString = NO;
|
|
|
|
if (name == nil || (pos = [sets indexOfObject: name]) == NSNotFound)
|
|
|
|
{
|
2003-05-24 12:40:54 +00:00
|
|
|
[label setTitle: _(@"No Type")];
|
1999-12-23 16:36:51 +00:00
|
|
|
[value setStringValue: @""];
|
|
|
|
[okButton setEnabled: NO];
|
|
|
|
}
|
|
|
|
else if ([gets objectForKey: name] != nil)
|
|
|
|
{
|
|
|
|
SEL get = NSSelectorFromString([gets objectForKey: name]);
|
|
|
|
NSString *type = [types objectForKey: name];
|
|
|
|
|
|
|
|
[label setTitle: type];
|
|
|
|
if (type == typeChar)
|
|
|
|
{
|
|
|
|
char v;
|
|
|
|
char (*imp)();
|
|
|
|
|
|
|
|
imp = (char (*)())[object methodForSelector: get];
|
|
|
|
v = (*imp)(object, get);
|
|
|
|
[value setStringValue: [NSString stringWithFormat: @"%d", v]];
|
|
|
|
}
|
|
|
|
else if (type == typeUChar)
|
|
|
|
{
|
|
|
|
unsigned char v;
|
|
|
|
unsigned char (*imp)();
|
|
|
|
|
|
|
|
imp = (unsigned char (*)())[object methodForSelector: get];
|
|
|
|
v = (*imp)(object, get);
|
|
|
|
[value setStringValue: [NSString stringWithFormat: @"%d", v]];
|
|
|
|
}
|
|
|
|
else if (type == typeInt)
|
|
|
|
{
|
|
|
|
int v;
|
|
|
|
int (*imp)();
|
|
|
|
|
|
|
|
imp = (int (*)())[object methodForSelector: get];
|
|
|
|
v = (*imp)(object, get);
|
|
|
|
[value setStringValue: [NSString stringWithFormat: @"%d", v]];
|
|
|
|
}
|
|
|
|
else if (type == typeUInt)
|
|
|
|
{
|
|
|
|
unsigned v;
|
|
|
|
unsigned (*imp)();
|
|
|
|
|
2013-11-04 15:02:25 +00:00
|
|
|
imp = (unsigned (*)()) [object methodForSelector: get];
|
1999-12-23 16:36:51 +00:00
|
|
|
v = (*imp)(object, get);
|
|
|
|
[value setStringValue: [NSString stringWithFormat: @"%u", v]];
|
|
|
|
}
|
|
|
|
else if (type == typeFloat)
|
|
|
|
{
|
|
|
|
float v;
|
|
|
|
float (*imp)();
|
|
|
|
|
|
|
|
imp = (float (*)())[object methodForSelector: get];
|
|
|
|
v = (*imp)(object, get);
|
|
|
|
[value setStringValue: [NSString stringWithFormat: @"%f", v]];
|
|
|
|
}
|
|
|
|
else if (type == typeDouble)
|
|
|
|
{
|
|
|
|
double v;
|
|
|
|
double (*imp)();
|
|
|
|
|
|
|
|
imp = (double (*)())[object methodForSelector: get];
|
|
|
|
v = (*imp)(object, get);
|
|
|
|
[value setStringValue: [NSString stringWithFormat: @"%g", v]];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
id v;
|
|
|
|
IMP imp = [object methodForSelector: get];
|
|
|
|
|
|
|
|
v = (*imp)(object, get);
|
|
|
|
if (v != nil && [v isKindOfClass: [NSString class]] == YES)
|
|
|
|
{
|
|
|
|
isString = YES; /* Existing value is a string. */
|
|
|
|
}
|
|
|
|
[value setStringValue: [v description]];
|
|
|
|
}
|
|
|
|
[okButton setEnabled: YES];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-05-24 12:40:54 +00:00
|
|
|
[label setTitle: [NSString stringWithFormat: _(@"%@ - value unknown"),
|
1999-12-23 16:36:51 +00:00
|
|
|
[types objectForKey: name]]];
|
|
|
|
[value setStringValue: @""];
|
|
|
|
[okButton setEnabled: YES];
|
|
|
|
}
|
1999-12-23 11:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) wantsButtons
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|