mirror of
https://github.com/gnustep/apps-gorm.git
synced 2025-04-22 22:20:44 +00:00
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:
parent
81e2adb9d1
commit
5e2010cc03
4 changed files with 357 additions and 21 deletions
|
@ -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
1
Gorm.h
|
@ -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;
|
||||
|
|
|
@ -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
17
README
|
@ -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.
|
||||
|
||||
|
|
Loading…
Reference in a new issue