home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / MiscKit1.2.6 / Palettes / MiscTeePalette / MiscTeeConnectorInspector.m < prev    next >
Encoding:
Text File  |  1994-06-16  |  9.7 KB  |  459 lines

  1. //
  2. //    MiscTeeConnectorInspector.m -- The inspector for the multiple connector
  3. //                                   object that's the inspectee.
  4. //
  5. //        Written by David Fedchenko.  Copyright 1994 by David Fedchenko.
  6. //                Version 1.0  All rights reserved.
  7. //
  8. //        This notice may not be removed from this source code.
  9. //
  10. //    This object is included in the MiscKit by permission from the author
  11. //    and its use is governed by the MiscKit license, found in the file
  12. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  13. //    for a list of all applicable permissions and restrictions.
  14. //    
  15.  
  16. #import "MiscTeeConnectorInspector.h"
  17. #import "MiscTee.subproj/MiscTeeConnector.h"
  18. #import "MiscDimpleCell.h"
  19. #import "StringList.bproj/StringList.h"
  20. #import <objc/objc-runtime.h>
  21.  
  22. @implementation MiscTee (ConnectionsInspector)
  23.  
  24. -(const char *) getConnectInspectorClassName
  25.     {
  26.     return "MiscTeeConnectorInspector";
  27.     }
  28.  
  29. -(NXImage *) getIBImage
  30.     {
  31.     id    idBundle;
  32.     id    idImage;
  33.     char buf[MAXPATHLEN + 1];
  34.     
  35.     idBundle = [NXBundle bundleForClass:[MiscTeeConnectorInspector class]];
  36.     [idBundle getPath:buf forResource:"MiscTee" ofType:"tiff"];
  37.     idImage = [[NXImage alloc] initFromFile:buf];
  38.     
  39.     return idImage;
  40.     }
  41.  
  42. @end
  43.  
  44. @implementation MiscTeeConnectorInspector
  45.  
  46. - init
  47.     {
  48.     char buf[MAXPATHLEN + 1];
  49.     id idBundle;
  50.     NXStream * stream;
  51.     char * pch;
  52.     int len;
  53.     int maxlen;
  54.     
  55.     [super init];
  56.     
  57.     idBundle = [NXBundle bundleForClass:[self class]];
  58.     [idBundle getPath:buf forResource:"MiscTeeConnectorInspector"
  59.               ofType:"nib"];
  60.     [NXApp loadNibFile:buf owner:self withNames:NO fromZone:[self zone]];
  61.     
  62.     connectorList = [[List alloc] init];
  63.     idConnector = nil;
  64.     
  65.     // Load in the StringList class for the following stuff.  We have to
  66.     // do it by hand since the user may have the StringList palette loaded
  67.     // which means we'll wind up with a rld() problem.  So we load it if
  68.     // it doesn't already exist.  This will hopefully keep the problems
  69.     // from arising.
  70.     if (objc_lookUpClass("StringList") == nil)
  71.         {
  72.         id idBundleClass;
  73.         
  74.         [idBundle getPath:buf forResource:"StringList" ofType:"bundle"];
  75.         idBundleClass = [[NXBundle allocFromZone:[self zone]] 
  76.                             initForDirectory:buf];
  77.         if ([idBundleClass classNamed:"StringList"] == nil)
  78.             {
  79.             // we can't create the list to set it up, so bail out of here now
  80.             NXLogError("MiscTeeInspector couldn't load StringList class.");
  81.             return self;
  82.             }
  83.         }
  84.     
  85.     // Load the names of selectors that have a single id argument that
  86.     // are not actions.  This is to keep the noise down in the display.
  87.     // The file is kept in the .palette wrapper so the list can easily
  88.     // be edited by somebody who cares about it.
  89.     idNonActions = [[objc_lookUpClass("StringList") alloc] init];
  90.     [idBundle getPath:buf forResource:"NonActions" ofType:"txt"];
  91.     stream = NXMapFile(buf, NX_READONLY);
  92.     if (stream)
  93.         {
  94.         NXGetMemoryBuffer(stream, &pch, &len, &maxlen);
  95.         [idNonActions addDelimitedStrings:pch delimiters:"\n"
  96.                       ifAbsent:NO sorted:YES at:0];                
  97.         NXClose(stream);
  98.         }
  99.     
  100.     return self;
  101.     }
  102.  
  103. - free
  104.     {
  105.     [connectorList free];
  106.     
  107.     return [super free];
  108.     }
  109.  
  110. - awakeFromNib
  111.     {
  112.     [outletBrowser setDoubleAction:@selector(ok:)];
  113.     [outletBrowser setCellClass:[MiscDimpleCell class]];
  114.     
  115.     // I'm not sure why I have to do the following, but if I don't the
  116.     // matrix is filled with NXBrowserCells which won't work here.
  117.     [[[outletBrowser matrixInColumn:0] setCellClass:[MiscDimpleCell class]]
  118.                                        setPrototype:nil];
  119.     return self;
  120.     }
  121.  
  122. - ok:sender
  123.     {
  124.     [self findConnection];
  125.  
  126.     if ([okButton tag] == 0)
  127.         {
  128.         idConnector = [[MiscTeeConnector alloc] init];
  129.         [idConnector setDestination:[NXApp connectDestination]];
  130.         [idConnector setSource:object];
  131.         if ([outletBrowser selectedColumn] == 1)
  132.             {
  133.             const char * sz;
  134.             
  135.             sz = [[outletBrowser selectedCell] stringValue];
  136.             [idConnector setAction:sel_getUid(sz)];
  137.             }
  138.         else
  139.             {
  140.             [idConnector setAction:NULL];
  141.             [outletBrowser reloadColumn:1];
  142.             }
  143.         
  144.         [[NXApp activeDocument] addConnector:idConnector];
  145.         }
  146.     else if ([okButton tag] == 1)
  147.         {
  148.         [[NXApp activeDocument] removeConnector:idConnector];
  149.         [idConnector free];
  150.         idConnector = nil;
  151.         }
  152.     
  153.     [self revert:self];
  154.     
  155.     return [super ok:sender];
  156.     }
  157.  
  158. - revert:sender
  159.     {
  160.     int i = [self findConnection];
  161.     
  162.     if (i == -1 && [connectorList count])
  163.         {
  164.         i = 0;
  165.         idConnector = [connectorList objectAt:0];
  166.         }
  167.     
  168.     if (idConnector)
  169.         {
  170.         [[okButton setTitle:"Disconnect"] setTag:1];
  171.         [okButton setEnabled:YES];
  172.         }
  173.     else if (i > -1)
  174.         {
  175.         // a new connection
  176.         [[okButton setTitle:"Connect"] setTag:0];
  177.         [okButton setEnabled:YES];
  178.         i = [connectorList count];
  179.         }
  180.     
  181.     [window disableFlushWindow];
  182.     if (![outletBrowser isLoaded])
  183.         {
  184.         [outletBrowser loadColumnZero];
  185.         }
  186.     else
  187.         {
  188.         [outletBrowser reloadColumn:0];
  189.         [[outletBrowser matrixInColumn:0] selectCellAt:i :0];
  190.         }
  191.     
  192.     if ([outletBrowser matrixInColumn:1] == nil)
  193.         {
  194.         [outletBrowser addColumn];
  195.         }
  196.     else
  197.         {
  198.         [outletBrowser reloadColumn:1];
  199.         [[outletBrowser matrixInColumn:1] selectCellAt:-1 :-1];
  200.         }
  201.     [window reenableFlushWindow];
  202.     [window flushWindowIfNeeded];
  203.     
  204.     if (sender == self)
  205.         {
  206.         return self;
  207.         }
  208.     else
  209.         {
  210.         return [super revert:sender];
  211.         }
  212.     }
  213.  
  214. - (BOOL)wantsButtons
  215.     {
  216.     return YES;
  217.     }
  218.  
  219. - refreshList
  220.     {
  221.     [connectorList empty];
  222.     
  223.     [[NXApp activeDocument] listConnectors:connectorList
  224.                             forSource:object
  225.                             filterClass:[MiscTeeConnector class]];
  226.  
  227.     return self;
  228.     }
  229.  
  230. -(int) findConnection
  231.     {
  232.     int    i = -1;
  233.     int    c;
  234.     id    idCon;
  235.     
  236.     [self refreshList];
  237.     
  238.     idConnector = nil;
  239.     
  240.     if ([NXApp isConnecting])
  241.         {
  242.         c = [connectorList count];
  243.         for (i = 0; i < c; i++)
  244.             {
  245.             idCon = [connectorList objectAt:i];
  246.             if ([idCon destination] == [NXApp connectDestination])
  247.                 {
  248.                 idConnector = idCon;
  249.                 break;
  250.                 }
  251.             }
  252.         }
  253.     
  254.     return i;
  255.     }
  256.  
  257. - clickOutlet:sender
  258.     {
  259.     int i;
  260.     
  261.     i = [[sender matrixInColumn:0] selectedRow];
  262.     
  263.     if (i < [connectorList count])
  264.         {
  265.         idConnector = [connectorList objectAt:i];
  266.         
  267.         [NXApp displayConnectionBetween:[idConnector source]
  268.                                     and:[idConnector destination]];
  269.         }
  270.     else
  271.         {
  272.         idConnector = nil;
  273.         }
  274.         
  275.     return self;
  276.     }
  277.  
  278. -(int) browser:sender fillMatrix:matrix inColumn:(int)column
  279.     {
  280.     int     c = 0;
  281.     int     i;
  282.     id        idDest;
  283.     id        idCell;
  284.     char    szName[500];
  285.     
  286.     if (column == 0)
  287.         {
  288.         [self refreshList];
  289.         c = [connectorList count];
  290.         [matrix renewRows:((idConnector == nil) ? c + 1 : c) cols:1];
  291.         for (i = 0; i < c; i++)
  292.             {
  293.             idDest = [[connectorList objectAt:i] destination];
  294.             idCell = [matrix cellAt:i :0];
  295.             strcpy(szName, [idDest name]);
  296.             [self cleanClassName:szName];
  297.             [idCell setStringValue:szName];
  298.             [idCell setLoaded:YES];
  299.             if ([[connectorList objectAt:i] action])
  300.                 {
  301.                 [idCell setMarked:NO];
  302.                 [idCell setLeaf:NO];
  303.                 }
  304.             else
  305.                 {
  306.                 [idCell setMarked:YES];
  307.                 }
  308.             }
  309.         
  310.         if (idConnector == nil && [NXApp isConnecting])
  311.             {
  312.             idCell = [matrix cellAt:c :0];
  313.             strcpy(szName, [[NXApp connectDestination] name]);
  314.             [self cleanClassName:szName];
  315.             [idCell setStringValue:szName];
  316.             [[idCell setLoaded:YES] setLeaf:NO];
  317.             c++;
  318.             }
  319.         
  320.         [matrix sizeToCells];
  321.         }
  322.     else if (column == 1)
  323.         {
  324.         id    idActionList;
  325.         id    idSelected = [[objc_lookUpClass("StringList") alloc] init];
  326.         int count;
  327.         SEL    selAction;
  328.         const char * sz;
  329.         
  330.         if (idConnector || [NXApp isConnecting])
  331.             {
  332.             if ((idConnector == nil) || [idConnector action])
  333.                 {
  334.                 if (idConnector == nil)
  335.                     {
  336.                     strcpy(szName, [[[NXApp connectDestination] class] name]);
  337.                     }
  338.                 else
  339.                     {
  340.                     strcpy(szName, [[[idConnector destination] class] name]);
  341.                     }
  342.                 [self cleanClassName:szName];
  343.                 idActionList = [self getActions:szName];
  344.                 c = [idActionList count];
  345.                 
  346.                 [matrix renewRows:c cols:1];
  347.                 count = 0;
  348.                 for (i = 0; i < c ; i++)
  349.                     {
  350.                     selAction = *(SEL *)[idActionList elementAt:i];
  351.                     sz = sel_getName(selAction);
  352.                     if (![idNonActions stringExists:sz])
  353.                         {
  354.                         [idSelected addString:sz];
  355.                         count++;
  356.                         }
  357.                     }
  358.                 
  359.                 [idSelected sortStrings:self];
  360.                 count = [idSelected count];
  361.                 for (i = 0; i < count ; i++)
  362.                     {
  363.                     idCell = [matrix cellAt:i :0];
  364.                     [idCell setStringValue:[idSelected stringAt:i]];
  365.                     [[[idCell setLoaded:YES] setLeaf:YES] setMarked:NO];
  366.                     if ((idConnector != nil) && [idConnector action])
  367.                         {
  368.                         if (!strcmp(sel_getName([idConnector action]),
  369.                                     [idSelected stringAt:i]))
  370.                             {
  371.                             [idCell setMarked:YES];
  372.                             }
  373.                         }
  374.                     }
  375.                 
  376.                 c = count;
  377.                 [matrix renewRows:c cols:1];
  378.                 }
  379.             else
  380.                 {
  381.                 c = 0;
  382.                 [matrix renewRows:0 cols:1];
  383.                 }
  384.             }
  385.         
  386.         [matrix sizeToCells];
  387.         [[idSelected freeStrings] free];
  388.         
  389.         }
  390.     
  391.     return c;
  392.     }
  393.  
  394. - cleanClassName:(char *)sz
  395.     {
  396.     char * pEnd = sz + strlen(sz);
  397.     
  398.     // rename a few specific classes that IB sneaks in the mix
  399.     // it's looks like the only ones we have to worry about just have
  400.     // "Template" stuck on the end.
  401.     
  402.     if (!strncmp("Template", pEnd - 8, 8))
  403.         {
  404.         *(pEnd - 8) = 0;
  405.         }
  406.     
  407.     return self;
  408.     }
  409.  
  410.  
  411. void walk_method_list(struct objc_method_list * pMethods, id idStore)
  412.     {
  413.     const char * sz;
  414.     int    i;
  415.     
  416.     for (i = 0; i < pMethods->method_count; i++)
  417.         {
  418.         if (!strcmp(pMethods->method_list[i].method_types, "@12@8:12@16"))
  419.             {
  420.             sz = sel_getName(pMethods->method_list[i].method_name);
  421.             if (*sz != '_')
  422.                 {
  423.                 [idStore addElement:&pMethods->method_list[i].method_name];
  424.                 }
  425.             }
  426.         }
  427.     
  428.     
  429.     return;
  430.     }
  431.  
  432. - getActions:(const char *)szClassName
  433.     {
  434.     id    idStore;
  435.     struct objc_method_list * pMethods;
  436.     struct objc_class * pClass;
  437.     
  438.     idStore = [[Storage alloc] initCount:0
  439.                                elementSize:sizeof(SEL)
  440.                                description:@encode(SEL)];
  441.     
  442.     pClass = objc_lookUpClass(szClassName);
  443.     while (pClass)
  444.         {
  445.         pMethods = pClass->methods;
  446.         while (pMethods)
  447.             {
  448.             walk_method_list(pMethods, idStore);
  449.             
  450.             pMethods = pMethods->method_next;
  451.             }
  452.         pClass = pClass->super_class;
  453.         }
  454.     
  455.     return idStore;
  456.     }
  457.  
  458. @end
  459.