This is MiscTeeConnectorInspector.m in view mode; [Download] [Up]
// // 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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.