home *** CD-ROM | disk | FTP | other *** search
- //
- // MiscTeeConnectorInspector.m -- The inspector for the multiple connector
- // object that's the inspectee.
- //
- // Written by David Fedchenko. Copyright 1994 by David Fedchenko.
- // Version 1.0 All rights reserved.
- //
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the author
- // and its use is governed by the MiscKit license, found in the file
- // "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
-
- #import "MiscTeeConnectorInspector.h"
- #import "MiscTee.subproj/MiscTeeConnector.h"
- #import "MiscDimpleCell.h"
- #import "StringList.bproj/StringList.h"
- #import <objc/objc-runtime.h>
-
- @implementation MiscTee (ConnectionsInspector)
-
- -(const char *) getConnectInspectorClassName
- {
- return "MiscTeeConnectorInspector";
- }
-
- -(NXImage *) getIBImage
- {
- id idBundle;
- id idImage;
- char buf[MAXPATHLEN + 1];
-
- idBundle = [NXBundle bundleForClass:[MiscTeeConnectorInspector class]];
- [idBundle getPath:buf forResource:"MiscTee" ofType:"tiff"];
- idImage = [[NXImage alloc] initFromFile:buf];
-
- return idImage;
- }
-
- @end
-
- @implementation MiscTeeConnectorInspector
-
- - init
- {
- char buf[MAXPATHLEN + 1];
- id idBundle;
- NXStream * stream;
- char * pch;
- int len;
- int maxlen;
-
- [super init];
-
- idBundle = [NXBundle bundleForClass:[self class]];
- [idBundle getPath:buf forResource:"MiscTeeConnectorInspector"
- ofType:"nib"];
- [NXApp loadNibFile:buf owner:self withNames:NO fromZone:[self zone]];
-
- connectorList = [[List alloc] init];
- idConnector = nil;
-
- // Load in the StringList class for the following stuff. We have to
- // do it by hand since the user may have the StringList palette loaded
- // which means we'll wind up with a rld() problem. So we load it if
- // it doesn't already exist. This will hopefully keep the problems
- // from arising.
- if (objc_lookUpClass("StringList") == nil)
- {
- id idBundleClass;
-
- [idBundle getPath:buf forResource:"StringList" ofType:"bundle"];
- idBundleClass = [[NXBundle allocFromZone:[self zone]]
- initForDirectory:buf];
- if ([idBundleClass classNamed:"StringList"] == nil)
- {
- // we can't create the list to set it up, so bail out of here now
- NXLogError("MiscTeeInspector couldn't load StringList class.");
- return self;
- }
- }
-
- // Load the names of selectors that have a single id argument that
- // are not actions. This is to keep the noise down in the display.
- // The file is kept in the .palette wrapper so the list can easily
- // be edited by somebody who cares about it.
- idNonActions = [[objc_lookUpClass("StringList") alloc] init];
- [idBundle getPath:buf forResource:"NonActions" ofType:"txt"];
- stream = NXMapFile(buf, NX_READONLY);
- if (stream)
- {
- NXGetMemoryBuffer(stream, &pch, &len, &maxlen);
- [idNonActions addDelimitedStrings:pch delimiters:"\n"
- ifAbsent:NO sorted:YES at:0];
- NXClose(stream);
- }
-
- return self;
- }
-
- - free
- {
- [connectorList free];
-
- return [super free];
- }
-
- - awakeFromNib
- {
- [outletBrowser setDoubleAction:@selector(ok:)];
- [outletBrowser setCellClass:[MiscDimpleCell class]];
-
- // I'm not sure why I have to do the following, but if I don't the
- // matrix is filled with NXBrowserCells which won't work here.
- [[[outletBrowser matrixInColumn:0] setCellClass:[MiscDimpleCell class]]
- setPrototype:nil];
- return self;
- }
-
- - ok:sender
- {
- [self findConnection];
-
- if ([okButton tag] == 0)
- {
- idConnector = [[MiscTeeConnector alloc] init];
- [idConnector setDestination:[NXApp connectDestination]];
- [idConnector setSource:object];
- if ([outletBrowser selectedColumn] == 1)
- {
- const char * sz;
-
- sz = [[outletBrowser selectedCell] stringValue];
- [idConnector setAction:sel_getUid(sz)];
- }
- else
- {
- [idConnector setAction:NULL];
- [outletBrowser reloadColumn:1];
- }
-
- [[NXApp activeDocument] addConnector:idConnector];
- }
- else if ([okButton tag] == 1)
- {
- [[NXApp activeDocument] removeConnector:idConnector];
- [idConnector free];
- idConnector = nil;
- }
-
- [self revert:self];
-
- return [super ok:sender];
- }
-
- - revert:sender
- {
- int i = [self findConnection];
-
- if (i == -1 && [connectorList count])
- {
- i = 0;
- idConnector = [connectorList objectAt:0];
- }
-
- if (idConnector)
- {
- [[okButton setTitle:"Disconnect"] setTag:1];
- [okButton setEnabled:YES];
- }
- else if (i > -1)
- {
- // a new connection
- [[okButton setTitle:"Connect"] setTag:0];
- [okButton setEnabled:YES];
- i = [connectorList count];
- }
-
- [window disableFlushWindow];
- if (![outletBrowser isLoaded])
- {
- [outletBrowser loadColumnZero];
- }
- else
- {
- [outletBrowser reloadColumn:0];
- [[outletBrowser matrixInColumn:0] selectCellAt:i :0];
- }
-
- if ([outletBrowser matrixInColumn:1] == nil)
- {
- [outletBrowser addColumn];
- }
- else
- {
- [outletBrowser reloadColumn:1];
- [[outletBrowser matrixInColumn:1] selectCellAt:-1 :-1];
- }
- [window reenableFlushWindow];
- [window flushWindowIfNeeded];
-
- if (sender == self)
- {
- return self;
- }
- else
- {
- return [super revert:sender];
- }
- }
-
- - (BOOL)wantsButtons
- {
- return YES;
- }
-
- - refreshList
- {
- [connectorList empty];
-
- [[NXApp activeDocument] listConnectors:connectorList
- forSource:object
- filterClass:[MiscTeeConnector class]];
-
- return self;
- }
-
- -(int) findConnection
- {
- int i = -1;
- int c;
- id idCon;
-
- [self refreshList];
-
- idConnector = nil;
-
- if ([NXApp isConnecting])
- {
- c = [connectorList count];
- for (i = 0; i < c; i++)
- {
- idCon = [connectorList objectAt:i];
- if ([idCon destination] == [NXApp connectDestination])
- {
- idConnector = idCon;
- break;
- }
- }
- }
-
- return i;
- }
-
- - clickOutlet:sender
- {
- int i;
-
- i = [[sender matrixInColumn:0] selectedRow];
-
- if (i < [connectorList count])
- {
- idConnector = [connectorList objectAt:i];
-
- [NXApp displayConnectionBetween:[idConnector source]
- and:[idConnector destination]];
- }
- else
- {
- idConnector = nil;
- }
-
- return self;
- }
-
- -(int) browser:sender fillMatrix:matrix inColumn:(int)column
- {
- int c = 0;
- int i;
- id idDest;
- id idCell;
- char szName[500];
-
- if (column == 0)
- {
- [self refreshList];
- c = [connectorList count];
- [matrix renewRows:((idConnector == nil) ? c + 1 : c) cols:1];
- for (i = 0; i < c; i++)
- {
- idDest = [[connectorList objectAt:i] destination];
- idCell = [matrix cellAt:i :0];
- strcpy(szName, [idDest name]);
- [self cleanClassName:szName];
- [idCell setStringValue:szName];
- [idCell setLoaded:YES];
- if ([[connectorList objectAt:i] action])
- {
- [idCell setMarked:NO];
- [idCell setLeaf:NO];
- }
- else
- {
- [idCell setMarked:YES];
- }
- }
-
- if (idConnector == nil && [NXApp isConnecting])
- {
- idCell = [matrix cellAt:c :0];
- strcpy(szName, [[NXApp connectDestination] name]);
- [self cleanClassName:szName];
- [idCell setStringValue:szName];
- [[idCell setLoaded:YES] setLeaf:NO];
- c++;
- }
-
- [matrix sizeToCells];
- }
- else if (column == 1)
- {
- id idActionList;
- id idSelected = [[objc_lookUpClass("StringList") alloc] init];
- int count;
- SEL selAction;
- const char * sz;
-
- if (idConnector || [NXApp isConnecting])
- {
- if ((idConnector == nil) || [idConnector action])
- {
- if (idConnector == nil)
- {
- strcpy(szName, [[[NXApp connectDestination] class] name]);
- }
- else
- {
- strcpy(szName, [[[idConnector destination] class] name]);
- }
- [self cleanClassName:szName];
- idActionList = [self getActions:szName];
- c = [idActionList count];
-
- [matrix renewRows:c cols:1];
- count = 0;
- for (i = 0; i < c ; i++)
- {
- selAction = *(SEL *)[idActionList elementAt:i];
- sz = sel_getName(selAction);
- if (![idNonActions stringExists:sz])
- {
- [idSelected addString:sz];
- count++;
- }
- }
-
- [idSelected sortStrings:self];
- count = [idSelected count];
- for (i = 0; i < count ; i++)
- {
- idCell = [matrix cellAt:i :0];
- [idCell setStringValue:[idSelected stringAt:i]];
- [[[idCell setLoaded:YES] setLeaf:YES] setMarked:NO];
- if ((idConnector != nil) && [idConnector action])
- {
- if (!strcmp(sel_getName([idConnector action]),
- [idSelected stringAt:i]))
- {
- [idCell setMarked:YES];
- }
- }
- }
-
- c = count;
- [matrix renewRows:c cols:1];
- }
- else
- {
- c = 0;
- [matrix renewRows:0 cols:1];
- }
- }
-
- [matrix sizeToCells];
- [[idSelected freeStrings] free];
-
- }
-
- return c;
- }
-
- - cleanClassName:(char *)sz
- {
- char * pEnd = sz + strlen(sz);
-
- // rename a few specific classes that IB sneaks in the mix
- // it's looks like the only ones we have to worry about just have
- // "Template" stuck on the end.
-
- if (!strncmp("Template", pEnd - 8, 8))
- {
- *(pEnd - 8) = 0;
- }
-
- return self;
- }
-
-
- void walk_method_list(struct objc_method_list * pMethods, id idStore)
- {
- const char * sz;
- int i;
-
- for (i = 0; i < pMethods->method_count; i++)
- {
- if (!strcmp(pMethods->method_list[i].method_types, "@12@8:12@16"))
- {
- sz = sel_getName(pMethods->method_list[i].method_name);
- if (*sz != '_')
- {
- [idStore addElement:&pMethods->method_list[i].method_name];
- }
- }
- }
-
-
- return;
- }
-
- - getActions:(const char *)szClassName
- {
- id idStore;
- struct objc_method_list * pMethods;
- struct objc_class * pClass;
-
- idStore = [[Storage alloc] initCount:0
- elementSize:sizeof(SEL)
- description:@encode(SEL)];
-
- pClass = objc_lookUpClass(szClassName);
- while (pClass)
- {
- pMethods = pClass->methods;
- while (pMethods)
- {
- walk_method_list(pMethods, idStore);
-
- pMethods = pMethods->method_next;
- }
- pClass = pClass->super_class;
- }
-
- return idStore;
- }
-
- @end
-