Various improvements

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/gorm/trunk@5617 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 1999-12-23 16:36:51 +00:00
parent 81e2adb9d1
commit 5e2010cc03
4 changed files with 357 additions and 21 deletions

View file

@ -1,3 +1,7 @@
Thu Dec 23 16:32:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
Added generic object inspector.
Wed Dec 22 12:16:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
Replaced the two NeXT images for sounds and classes.

1
Gorm.h
View file

@ -182,6 +182,7 @@ extern NSString *IBDidEndTestingInterfaceNotification;
inEditor: (id<IBEditors>)anEditor
create: (BOOL)flag;
- (NSString*) nameForObject: (id)anObject;
- (id) objectForName: (NSString*)aName;
- (NSArray*) objects;
- (id<IBEditors>) openEditorForObject: (id)anObject;
- (id<IBEditors>) parentEditorForEditor: (id<IBEditors>)anEditor;

View file

@ -24,13 +24,24 @@
#include "GormPrivate.h"
static NSString *typeId = @"Object";
static NSString *typeChar = @"Character or Boolean";
static NSString *typeUChar = @"Unsigned character/bool";
static NSString *typeInt = @"Integer";
static NSString *typeUInt = @"Unsigned integer";
static NSString *typeFloat = @"Float";
static NSString *typeDouble = @"Double";
@interface GormObjectInspector : IBInspector
{
NSBrowser *browser;
NSArray *names;
NSArray *types;
NSButton *label;
NSText *value;
NSBrowser *browser;
NSMutableArray *sets;
NSMutableDictionary *gets;
NSMutableDictionary *types;
NSButton *label;
NSTextField *value;
BOOL isString;
}
- (void) updateButtons;
@end
@ -39,7 +50,7 @@
- (int) browser: (NSBrowser*)sender numberOfRowsInColumn: (int)column
{
return [names count];
return [sets count];
}
- (BOOL) browser: (NSBrowser*)sender
@ -60,9 +71,9 @@ selectCellWithString: (NSString*)title
atRow: (int)row
column: (int)col
{
if (row >= 0 && row < [names count])
if (row >= 0 && row < [sets count])
{
[aCell setStringValue: [names objectAtIndex: row]];
[aCell setStringValue: [sets objectAtIndex: row]];
[aCell setEnabled: YES];
}
else
@ -75,12 +86,10 @@ selectCellWithString: (NSString*)title
- (void) dealloc
{
RELEASE(label);
RELEASE(value);
RELEASE(names);
RELEASE(gets);
RELEASE(sets);
RELEASE(types);
RELEASE(okButton);
RELEASE(revertButton);
RELEASE(window);
[super dealloc];
}
@ -94,6 +103,10 @@ selectCellWithString: (NSString*)title
NSRect windowRect = NSMakeRect(0, 0, IVW, IVH-IVB);
NSRect rect;
sets = [NSMutableArray new];
gets = [NSMutableDictionary new];
types = [NSMutableDictionary new];
window = [[NSWindow alloc] initWithContentRect: windowRect
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreRetained
@ -139,29 +152,241 @@ selectCellWithString: (NSString*)title
[okButton setAutoresizingMask: NSViewMaxYMargin | NSViewMinXMargin];
[okButton setAction: @selector(ok:)];
[okButton setTarget: self];
[okButton setTitle: @"Add"];
[okButton setTitle: @"OK"];
[okButton setEnabled: NO];
revertButton = [[NSButton alloc] initWithFrame: NSMakeRect(0,0,90,20)];
[revertButton setAutoresizingMask: NSViewMaxYMargin | NSViewMinXMargin];
[revertButton setAction: @selector(revert:)];
[revertButton setTarget: self];
[revertButton setTitle: @"Revert"];
[revertButton setEnabled: NO];
revertButton = nil;
}
return self;
}
- (void) ok: (id)sender
{
NSString *name = [[browser selectedCell] stringValue];
unsigned pos;
if (name == nil || (pos = [sets indexOfObject: name]) == NSNotFound)
{
[label setTitle: @"No Type"];
[value setStringValue: @""];
[okButton setEnabled: NO];
}
else
{
SEL set = NSSelectorFromString(name);
NSString *type = [types objectForKey: name];
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];
result = NSRunAlertPanel(@"Settings",
[NSString stringWithFormat: @"Set object using '%@' as", v],
@"Object name", @"String", @"Class name");
if (result == NSAlertAlternateReturn)
{
(*imp)(object, set, v);
}
else if (result == NSAlertOtherReturn)
{
Class c = NSClassFromString(v);
if (c != 0)
{
(*imp)(object, set, [c new]);
}
}
else
{
id o = [[(id<IB>)NSApp activeDocument] objectForName: v];
if (o != nil)
{
(*imp)(object, set, o);
}
}
}
}
[self updateButtons];
}
}
- (void) setObject: (id)anObject
{
if (anObject != nil && anObject != object)
{
ASSIGN(object, anObject);
Class c = [anObject class];
ASSIGN(object, anObject);
[sets removeAllObjects];
[gets removeAllObjects];
[types removeAllObjects];
while (c != nil && c != [NSObject class])
{
struct objc_method_list *mlist = c->methods;
while (mlist != 0)
{
struct objc_method *methods = &mlist->method_list[0];
int count = mlist->method_count;
int i;
for (i = 0; i < count; i++)
{
SEL sSel = methods[i].method_name;
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];
const char *tInfo = methods[i].method_types;
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];
}
}
}
mlist = mlist->method_next;
}
c = [c superclass];
}
[sets sortUsingSelector: @selector(compare:)];
[browser loadColumnZero];
[self updateButtons];
}
@ -169,6 +394,97 @@ selectCellWithString: (NSString*)title
- (void) updateButtons
{
NSString *name = [[browser selectedCell] stringValue];
unsigned pos;
isString = NO;
if (name == nil || (pos = [sets indexOfObject: name]) == NSNotFound)
{
[label setTitle: @"No Type"];
[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)();
imp = (unsigned int (*)()) [object methodForSelector: get];
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
{
[label setTitle: [NSString stringWithFormat: @"%@ - value unknown",
[types objectForKey: name]]];
[value setStringValue: @""];
[okButton setEnabled: YES];
}
}
- (BOOL) wantsButtons

17
README
View file

@ -102,11 +102,26 @@ class of the files owner (it defaults to NSApplication).
There is a crude panel for setting the name of the selected object.
I've created a couple of new images and got rid of thh two NeXT images that
I've created a couple of new images and got rid of the two NeXT images that
were lurking in there.
There is a Testing directory, with a GormTest application that lets you load
a nib for testing - it assumes that the nib will set its FilesOwners delegate
to point to a window, and makes that window the key window ...
23 December 1999
Last work before christmas ...
Various bits of tidying up plus -
Added an evil hack of a generic attributes inspector ... This looks through
all the methods of the selected object to find those taking a single argument
and beginning with 'set'. It makes all these setting methods (whose argument
is a simple scalar type or an object) available for you to invoke from the
inspector panel.
This makes it possible to set pretty much any attribute of any object, but
you do need to have the GNUstep header files to hand, so you can tell what
numeric values to enter to achieve a desired result.