home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / YellowBox / Kits / MiscTableScroll-138.1 / Palettes / MiscTableScroll / Palette / MiscTableConnInspector.M < prev    next >
Encoding:
Text File  |  1998-03-31  |  23.4 KB  |  781 lines

  1. //=============================================================================
  2. //
  3. //    Copyright (C) 1996,1997,1998 by Paul S. McCarthy and Eric Sunshine.
  4. //        Written by Paul S. McCarthy and Eric Sunshine.
  5. //                All Rights Reserved.
  6. //
  7. //    This notice may not be removed from this source code.
  8. //
  9. //    This object is included in the MiscKit by permission from the authors
  10. //    and its use is governed by the MiscKit license, found in the file
  11. //    "License.rtf" in the MiscKit distribution.  Please refer to that file
  12. //    for a list of all applicable permissions and restrictions.
  13. //    
  14. //=============================================================================
  15. //-----------------------------------------------------------------------------
  16. // MiscTableConnInspector.M
  17. //
  18. //    A custom Interface Builder connection inspector so that the
  19. //    doubleTarget and doubleAction can be set.
  20. //
  21. //-----------------------------------------------------------------------------
  22. //-----------------------------------------------------------------------------
  23. // $Id: MiscTableConnInspector.M,v 1.11 98/03/30 00:03:02 sunshine Exp $
  24. // $Log:    MiscTableConnInspector.M,v $
  25. //  Revision 1.11  98/03/30  00:03:02  sunshine
  26. //  v138.1: #import was missing "MiscTableScroll/" for public header.
  27. //  
  28. //  Revision 1.10  97/06/18  09:46:14  sunshine
  29. //  v125.9: Worked around OPENSTEP 4.2 final release for NT Objective-C++
  30. //  compiler crash occuring when sending message to 'super' from within a
  31. //  category.  Also MISC_TABLE_CELL_ICON --> MISC_TABLE_CELL_IMAGE.
  32. //  
  33. //  Revision 1.9  97/04/15  08:34:03  sunshine
  34. //  v0.125.8: Hacked around OPENSTEP 4.2 (prerelease) compiler bug.  Compiler
  35. //  crashes if a message is sent to 'super' from within a category.
  36. //  Temporarily moved affected code to MiscTableConnector.M.
  37. //-----------------------------------------------------------------------------
  38. #import "MiscTableConnInspector.h"
  39. #import "MiscTableConnector.h"
  40. #import    <MiscTableScroll/MiscTableScroll.h>
  41.  
  42. extern "Objective-C" {
  43. #import <AppKit/NSImage.h>
  44. #import    <Foundation/NSArray.h>
  45. #import    <Foundation/NSBundle.h>
  46. #import    <Foundation/NSDictionary.h>
  47. #import <Foundation/NSSet.h>
  48. #import    <Foundation/NSString.h>
  49. }
  50.  
  51. enum MiscTSOutletSlot
  52.     {
  53.     MISC_TS_NAME_OS,
  54.     MISC_TS_CONN_OS,
  55.     MISC_TS_PTR_OS
  56.     };
  57.  
  58. enum MiscTSActionSlot
  59.     {
  60.     MISC_TS_NAME_AS,
  61.     MISC_TS_CONN_AS
  62.     };
  63.  
  64.  
  65. #define ICON_DIMPLE @"MiscTableDimple"
  66. #define ICON_ARROW  @"MiscTableRightArrow"
  67. #define ICON_BLANK  @"MiscBlankImage"
  68.  
  69. static NSImage* IMAGE_DIMPLE;
  70. static NSImage* IMAGE_ARROW;
  71. static NSImage* IMAGE_BLANK;
  72.  
  73. static NSString*    OUTLET_ACTION_FILE = @"MiscTableConnector";
  74. static NSDictionary*    OUTLET_ACTION_DICT = 0;
  75.  
  76. static id        FIRST_RESP = (id)~0;
  77. static NSString*    FIRST_RESP_NAME = @"FirstResponder";
  78.  
  79.  
  80. //=============================================================================
  81. // PRIVATE IB METHODS
  82. //=============================================================================
  83. @interface IBDocument: NSObject
  84. - (id)classData;    // (IBClassData)
  85. @end
  86.  
  87. @interface IBClassData: NSObject
  88. - (NSSet*)outletsOfClass:(NSString*)s;
  89. - (NSSet*)actionsOfClass:(NSString*)s;
  90. @end
  91.  
  92.  
  93. //=============================================================================
  94. // CATEGORIES OF PRIVATE IB CONNECTION CLASSES
  95. //=============================================================================
  96.  
  97. @interface NSIBConnector(MiscTableConnInspector)
  98. - (id)initSource:(id)src destination:(id)dst label:(id)lbl;
  99. - (NSString*)outletName;
  100. - (NSString*)actionName;
  101. - (NSString*)actionValue;
  102. @end
  103.  
  104. @implementation NSIBConnector(MiscTableConnInspector)
  105. - (id)initSource:(id)src destination:(id)dst label:(id)lbl
  106.     {
  107.     [self init];
  108.     [self setSource:src];
  109.     [self setDestination:dst];
  110.     [self setLabel:lbl];
  111.     return self;
  112.     }
  113. - (NSString*)outletName     { return [self label]; }
  114. - (NSString*)actionName     { return 0; }
  115. - (NSString*)actionValue { return 0; }
  116. @end
  117.  
  118. @interface NSIBControlConnector(MiscTableConnInspector)
  119. - (NSString*)outletName;
  120. - (NSString*)actionName;
  121. - (NSString*)actionValue;
  122. @end
  123.  
  124. @implementation NSIBControlConnector(MiscTableConnInspector)
  125. - (NSString*)outletName     { NSString* s = @"target"; return s; }
  126. - (NSString*)actionName     { NSString* s = @"action"; return s; }
  127. - (NSString*)actionValue { return [self label]; }
  128. @end
  129.  
  130.  
  131. //=============================================================================
  132. // TABLE SCROLL CATEGORY
  133. //=============================================================================
  134. @interface MiscTableScroll(MiscTableConnInspector)
  135. - (NSString*)connectInspectorClassName;
  136. @end
  137.  
  138. @implementation MiscTableScroll(MiscTableConnInspector)
  139. - (NSString*)connectInspectorClassName
  140.     { NSString* s = @"MiscTableConnInspector"; return s; }
  141. @end
  142.  
  143.  
  144. //=============================================================================
  145. // TABLE CONNECTOR CATEGORY
  146. //=============================================================================
  147. @interface MiscTableConnector(MiscTableConnInspector)
  148. - (NSString*)outletName;
  149. - (NSString*)actionName;
  150. - (id)initSource:(id)src destination:(id)dst label:(NSString*)lbl
  151.     outlet:(NSString*)out action:(NSString*)act;
  152. - (void)encodeWithCoder:(NSCoder*)aCoder;
  153. - (NSString*)nibLabel;
  154. @end
  155.  
  156. @implementation MiscTableConnector(MiscTableConnInspector)
  157.  
  158. - (NSString*)outletName { return outletName; }
  159. - (NSString*)actionName { return actionName; }
  160.  
  161. - (id)initSource:(id)src destination:(id)dst label:(NSString*)lbl
  162.     outlet:(NSString*)out action:(NSString*)act
  163.     {
  164.     [self superInitSource:src destination:dst label:lbl];
  165.     outletName = [out retain];
  166.     actionName = [act retain];
  167.     return self;
  168.     }
  169.  
  170. - (void)encodeWithCoder:(NSCoder*)coder
  171.     {
  172.     [self superEncodeWithCoder:coder];
  173.     [coder encodeObject:outletName];
  174.     [coder encodeObject:actionName];
  175.     }
  176.  
  177. - (id)nibLabel
  178.     {
  179.     return [NSString stringWithFormat:
  180.         @"%@/%@", [self outletName], [self actionValue] ];
  181.     }
  182.  
  183. @end
  184.  
  185.  
  186. //=============================================================================
  187. // TABLE CONNECTOR INSPECTOR IMPLEMENTATION
  188. //=============================================================================
  189. @implementation MiscTableConnInspector
  190.  
  191. //-----------------------------------------------------------------------------
  192. // +initialize
  193. //-----------------------------------------------------------------------------
  194. + (void)initialize
  195.     {
  196.     NSString* path;
  197.     NSBundle* bundle = [NSBundle bundleForClass:self];
  198.  
  199.     path = [bundle pathForImageResource:ICON_DIMPLE];
  200.     IMAGE_DIMPLE = [[NSImage alloc] initByReferencingFile:path];
  201.     [IMAGE_DIMPLE setName:ICON_DIMPLE];
  202.  
  203.     path = [bundle pathForImageResource:ICON_ARROW];
  204.     IMAGE_ARROW = [[NSImage alloc] initByReferencingFile:path];
  205.     [IMAGE_ARROW setName:ICON_ARROW];
  206.  
  207.     IMAGE_BLANK = [[NSImage alloc] init];
  208.     [IMAGE_BLANK setName:ICON_BLANK];
  209.  
  210.     path = [bundle pathForResource:OUTLET_ACTION_FILE ofType:@"strings"];
  211.     OUTLET_ACTION_DICT =
  212.         [[NSDictionary dictionaryWithContentsOfFile:path] retain];
  213.     }
  214.  
  215.  
  216. //-----------------------------------------------------------------------------
  217. // +actionForOutlet:
  218. //-----------------------------------------------------------------------------
  219. + (NSString*)actionForOutlet:(NSString*)name
  220.     {
  221.     return [OUTLET_ACTION_DICT objectForKey:name];
  222.     }
  223.  
  224.  
  225. //-----------------------------------------------------------------------------
  226. // -actionForOutlet:
  227. //-----------------------------------------------------------------------------
  228. - (NSString*)actionForOutlet:(NSString*)name
  229.     {
  230.     return [OUTLET_ACTION_DICT objectForKey:name];
  231.     }
  232.  
  233.  
  234. //-----------------------------------------------------------------------------
  235. // -dealloc
  236. //-----------------------------------------------------------------------------
  237. - (void)dealloc
  238.     {
  239.     [connList release];
  240.     [curout release];
  241.     [super dealloc];
  242.     }
  243.  
  244.  
  245. //-----------------------------------------------------------------------------
  246. // -initScroll:numCols:
  247. //-----------------------------------------------------------------------------
  248. - (void)initScroll:(MiscTableScroll*)scroll numCols:(int)numCols
  249.     {
  250.     [scroll setAutoSortRows:YES];
  251.     [scroll setSelectionMode:MISC_RADIO_MODE];
  252.     [scroll setDelegate:self];
  253.     [scroll setTarget:self];
  254.     [scroll setDoubleTarget:self];
  255.     for (int i = 0; i < numCols; i++)
  256.     [scroll addColumn];
  257.     }
  258.  
  259.  
  260. //-----------------------------------------------------------------------------
  261. // -init
  262. //-----------------------------------------------------------------------------
  263. - (id)init
  264.     {
  265.     [super init];
  266.  
  267.     connList = [[NSArray array] retain];
  268.  
  269.     [NSBundle loadNibNamed:[[self class] description] owner:self];
  270.  
  271.     [self initScroll:outletScroll numCols:3];
  272.     [outletScroll setAction:@selector(outletClick:)];
  273.     [outletScroll setDoubleAction:@selector(outletDblClick:)];
  274.     [outletScroll setColumn:MISC_TS_NAME_OS size:83];
  275.     [outletScroll setColumn:MISC_TS_NAME_OS title:@"Outlets"];
  276.     [outletScroll setColumn:MISC_TS_CONN_OS size:13];
  277.     [outletScroll setColumn:MISC_TS_CONN_OS sizeable:NO];
  278.     [outletScroll setColumn:MISC_TS_CONN_OS cellType:MISC_TABLE_CELL_IMAGE];
  279.     [outletScroll setColumn:MISC_TS_CONN_OS sortType:MISC_SORT_TAG];
  280.     [outletScroll setColumn:MISC_TS_PTR_OS size:13];
  281.     [outletScroll setColumn:MISC_TS_PTR_OS sizeable:NO];
  282.     [outletScroll setColumn:MISC_TS_PTR_OS cellType:MISC_TABLE_CELL_IMAGE];
  283.     [outletScroll setColumn:MISC_TS_PTR_OS sortType:MISC_SORT_TAG];
  284.     [outletScroll setColumn:MISC_TS_PTR_OS sortDirection:MISC_SORT_DESCENDING];
  285.  
  286.     [self initScroll:actionScroll numCols:2];
  287.     [actionScroll setAction:@selector(actionClick:)];
  288.     [actionScroll setDoubleAction:@selector(actionDblClick:)];
  289.     [actionScroll setColumn:MISC_TS_NAME_AS size:96];
  290.     [actionScroll setColumn:MISC_TS_NAME_AS title:@"Actions"];
  291.     [actionScroll setColumn:MISC_TS_CONN_AS size:13];
  292.     [actionScroll setColumn:MISC_TS_CONN_AS sizeable:NO];
  293.     [actionScroll setColumn:MISC_TS_CONN_AS cellType:MISC_TABLE_CELL_IMAGE];
  294.     [actionScroll setColumn:MISC_TS_CONN_AS sortType:MISC_SORT_TAG];
  295.     [actionScroll setColumn:MISC_TS_CONN_AS sortDirection:MISC_SORT_DESCENDING];
  296.  
  297.     [outletScroll setNextKeyView:actionScroll];
  298.     [actionScroll setNextKeyView:outletScroll];
  299.  
  300.     return self;
  301.     }
  302.  
  303.  
  304. //-----------------------------------------------------------------------------
  305. // classNameOf:
  306. //-----------------------------------------------------------------------------
  307. - (NSString*)classNameOf:(id)obj
  308.     {
  309.     if ([obj respondsToSelector:@selector(className)])
  310.     return [obj performSelector:@selector(className)];
  311.     else
  312.     return [[obj class] description];
  313.     }
  314.  
  315.  
  316. //-----------------------------------------------------------------------------
  317. // -getConnList
  318. //-----------------------------------------------------------------------------
  319. - (void)getConnList
  320.     {
  321.     [connList autorelease];
  322.     connList = [[[NSApp activeDocument]
  323.         connectorsForSource:[self object]] retain];
  324.     }
  325.  
  326.  
  327. //-----------------------------------------------------------------------------
  328. // -findConnectionForOutlet:
  329. //    Note: this method is only accurate when connList is valid.
  330. //-----------------------------------------------------------------------------
  331. - (id)findConnectionForOutlet:(NSString*)outletName
  332.     {
  333.     unsigned int const lim = [connList count];
  334.     for (unsigned int i = 0; i < lim; i++)
  335.     {
  336.     id conn = [connList objectAtIndex:i];
  337.     if ([outletName isEqualToString:[conn outletName]])
  338.         return conn;
  339.     }
  340.     return 0;
  341.     }
  342.  
  343.  
  344. //-----------------------------------------------------------------------------
  345. // -connectionForOutlet:
  346. //-----------------------------------------------------------------------------
  347. - (id)connectionForOutlet:(NSString*) outletName
  348.     {
  349.     [self getConnList];
  350.     return [self findConnectionForOutlet:outletName];
  351.     }
  352.  
  353.  
  354. //-----------------------------------------------------------------------------
  355. // virtualDestFor:
  356. //-----------------------------------------------------------------------------
  357. - (id)virtualDestFor:(id)dest
  358.     {
  359.     if (dest == 0 || [[self classNameOf:dest] isEqualToString:FIRST_RESP_NAME])
  360.     return FIRST_RESP;
  361.     return dest;
  362.     }
  363.  
  364.  
  365. //-----------------------------------------------------------------------------
  366. // realDestFor:
  367. //-----------------------------------------------------------------------------
  368. - (id)realDestFor:(id)dest
  369.     {
  370.     return (dest == FIRST_RESP ? 0 : dest);
  371.     }
  372.  
  373.  
  374. //-----------------------------------------------------------------------------
  375. // -set:outlet:
  376. //    Note: this method is only accurate when connList is valid.
  377. //-----------------------------------------------------------------------------
  378. - (void)set:(int)row outlet:(NSString*)name
  379.     {
  380.     id cell;
  381.     id conn = [self findConnectionForOutlet:name];
  382.     id dest = (conn == 0 ? 0 : [self virtualDestFor:[conn destination]]);
  383.  
  384.     [outletScroll setRow:row tag:int(dest)];
  385.  
  386.     [[outletScroll cellAtRow:row column:MISC_TS_NAME_OS] setStringValue:name];
  387.  
  388.     BOOL const is_connected = (conn != 0);
  389.     cell = [outletScroll cellAtRow:row column:MISC_TS_CONN_OS];
  390.     [cell setImage:(is_connected ? IMAGE_DIMPLE : IMAGE_BLANK)];
  391.     [cell setTag:int(is_connected)];
  392.  
  393.     BOOL const has_action = ([self actionForOutlet:name] != 0);
  394.     cell = [outletScroll cellAtRow:row column:MISC_TS_PTR_OS];
  395.     [cell setImage:(has_action ? IMAGE_ARROW : IMAGE_BLANK)];
  396.     [cell setTag:int(has_action)];
  397.     }
  398.  
  399.  
  400. //-----------------------------------------------------------------------------
  401. // -loadOutlets
  402. //    Note: this method is only accurate when connList is valid.
  403. //
  404. //    Note: For some silly reason, the -outletsOfClass: method filters
  405. //    out the "target" outlet.  (Who knows why -- must be more hardcoded
  406. //    internal IB junk.)  Therefore, we need to add it back in, manually.
  407. //-----------------------------------------------------------------------------
  408. - (void)loadOutlets
  409.     {
  410.     id doc = [NSApp activeDocument];
  411.     NSSet* list = [[doc classData] outletsOfClass:
  412.             [self classNameOf:[self object]]];
  413.     unsigned int const lim = [list count];
  414.     if (lim > 0)
  415.     {
  416.     id str;
  417.     [outletScroll renewRows:lim + 1];    // Add one for target.
  418.     NSEnumerator* enu = [list objectEnumerator];
  419.     for (int i = 0; (str = [enu nextObject]) != 0; i++)
  420.         [self set:i outlet:str];
  421.     [self set:lim outlet:@"target"];
  422.     [outletScroll sortRows];
  423.     }
  424.     else
  425.     [outletScroll empty];
  426.     }
  427.  
  428.  
  429. //-----------------------------------------------------------------------------
  430. // -selectedOutletName
  431. //-----------------------------------------------------------------------------
  432. - (NSString*)selectedOutletName
  433.     {
  434.     NSString* s = 0;
  435.     int const r = [outletScroll selectedRow];
  436.     if (r >= 0)
  437.     s = [outletScroll stringValueAtRow:r column:MISC_TS_NAME_OS];
  438.     return s;
  439.     }
  440.  
  441.  
  442. //-----------------------------------------------------------------------------
  443. // -shouldShowActions:
  444. //-----------------------------------------------------------------------------
  445. - (BOOL)shouldShowActions:(id*)old_dest
  446.     {
  447.     int const r = [outletScroll selectedRow];
  448.     if (r >= 0 && [outletScroll tagAtRow:r column:MISC_TS_PTR_OS] != 0)
  449.     {
  450.     *old_dest = (id)[outletScroll rowTag:r];
  451.     return YES;
  452.     }
  453.     return NO;
  454.     }
  455.  
  456.  
  457. //-----------------------------------------------------------------------------
  458. // -loadActions
  459. //-----------------------------------------------------------------------------
  460. - (void)loadActions
  461.     {
  462.     [actionScroll empty];
  463.     id old_dest = 0;
  464.     if ([self shouldShowActions:&old_dest])
  465.     {
  466.     int sel_row = -1;
  467.     id dest = (curdst != 0 ? curdst : old_dest);
  468.     if (dest == 0 && [NSApp isConnecting])
  469.         dest = [self virtualDestFor:[NSApp connectDestination]];
  470.     if (dest != 0)
  471.         {
  472.         id doc = [NSApp activeDocument];
  473.         NSString* lbl = 0;
  474.         if (dest == old_dest)
  475.         {
  476.         NSString* oname = [self selectedOutletName];
  477.         id conn = [self connectionForOutlet:oname];
  478.         if (conn != 0)
  479.             lbl = [conn label];
  480.         }
  481.  
  482.         NSString* className = (dest == FIRST_RESP ?
  483.                 FIRST_RESP_NAME : [self classNameOf:dest]);
  484.         NSSet* list = [[doc classData] actionsOfClass:className];
  485.         unsigned int const lim = [list count];
  486.         [actionScroll renewRows:lim];
  487.         id str;
  488.         NSEnumerator* enu = [list objectEnumerator];
  489.         for (int i = 0; (str = [enu nextObject]) != 0; i++)
  490.         {
  491.         [[actionScroll cellAtRow:i column:MISC_TS_NAME_AS]
  492.                 setStringValue:str];
  493.         BOOL const connected = lbl != 0 && [lbl isEqualToString:str];
  494.         id cell = [actionScroll cellAtRow:i column:MISC_TS_CONN_AS];
  495.         [cell setImage:(connected ? IMAGE_DIMPLE : IMAGE_BLANK)];
  496.         [cell setTag:int(connected)];
  497.         if (connected)
  498.             sel_row = i;
  499.         }
  500.         }
  501.     if ([actionScroll numberOfRows] > 0)
  502.         {
  503.         [actionScroll sortRows];
  504.         if (sel_row >= 0)
  505.         {
  506.         [actionScroll selectRow:sel_row];
  507.         [actionScroll scrollRowToVisible:sel_row];
  508.         }
  509.         }
  510.     }
  511.     }
  512.  
  513.  
  514. //-----------------------------------------------------------------------------
  515. // -selectOutlet:
  516. //-----------------------------------------------------------------------------
  517. - (void)selectOutlet:(NSString*)name
  518.     {
  519.     int row = -1;
  520.     if (name != 0 && [name length] > 0)
  521.     {
  522.     int const lim = [outletScroll numberOfRows];
  523.     for (int i = 0; i < lim; i++)
  524.         {
  525.         int const j = [outletScroll rowAtPosition:i];
  526.         NSString* t = [outletScroll stringValueAtRow:j
  527.                 column:MISC_TS_NAME_OS];
  528.         if (t != 0 && [t isEqualToString:name])
  529.         {
  530.         row = j;
  531.         break;
  532.         }
  533.         }
  534.     }
  535.     [outletScroll selectRow:row];
  536.     if (row >= 0)
  537.     [outletScroll scrollRowToVisible:row];
  538.     [self loadActions];
  539.     }
  540.  
  541.  
  542. //-----------------------------------------------------------------------------
  543. // -setCurout:
  544. //-----------------------------------------------------------------------------
  545. - (void)setCurout:(NSString*)newout
  546.     {
  547.     [curout autorelease];
  548.     curout = newout;
  549.     [curout retain];
  550.     }
  551.  
  552.  
  553. //-----------------------------------------------------------------------------
  554. // -outletClick:
  555. //-----------------------------------------------------------------------------
  556. - (void)outletClick:(id)sender
  557.     {
  558.     int const r = [outletScroll selectedRow];
  559.     if (r >= 0)
  560.     {
  561.     NSString* s = [outletScroll stringValueAtRow:r column:MISC_TS_NAME_OS];
  562.     cursrc = [self object];
  563.     [self setCurout:s];
  564.     id conn = [self connectionForOutlet:s];
  565.     if (conn != 0)
  566.         {
  567.         id dst = [conn destination];
  568.         curdst = [self virtualDestFor:dst];
  569.         [NSApp displayConnectionBetween:[conn source] and:dst];
  570.         }
  571.     else
  572.         curdst = 0;
  573.     }
  574.     [self loadActions];
  575.     }
  576.  
  577.  
  578. //-----------------------------------------------------------------------------
  579. // -outletDblClick:
  580. //    NOTE *1* The only action allowed on the outlet column for 
  581. //    target/action style outlets is breaking "old" connections that
  582. //    do not have an action set.
  583. //-----------------------------------------------------------------------------
  584. - (void)outletDblClick:(id)sender
  585.     {
  586.     int const r = [outletScroll selectedRow];
  587.     if (r >= 0)
  588.     {
  589.     id old_dest = 0;
  590.     id new_dest = 0;
  591.     id doc = [NSApp activeDocument];
  592.  
  593.     NSString* outletName =
  594.         [outletScroll stringValueAtRow:r column:MISC_TS_NAME_OS];
  595.     id conn = [self connectionForOutlet:outletName];
  596.  
  597.     BOOL do_break = NO;
  598.     BOOL do_make = NO;
  599.     BOOL const has_action =
  600.         (BOOL) [outletScroll tagAtRow:r column:MISC_TS_PTR_OS];
  601.     if (has_action)
  602.         {
  603.         do_break = (conn != 0 && [conn actionName] == 0);    // NOTE *1*
  604.         }
  605.     else
  606.         {
  607.         do_break = (conn != 0);
  608.         old_dest = [self virtualDestFor:[conn destination]];
  609.         new_dest = [self virtualDestFor:[NSApp connectDestination]];
  610.         do_make = (new_dest != FIRST_RESP && new_dest != old_dest);
  611.         }
  612.  
  613.     if (do_break)
  614.         [doc removeConnector:conn];
  615.  
  616.     if (do_make)
  617.         {
  618.         conn = [[NSIBOutletConnector alloc]
  619.             initSource:[self object]
  620.             destination:[self realDestFor:new_dest]
  621.             label:outletName];
  622.         [doc addConnector:conn];
  623.         }
  624.  
  625.     if (do_break || do_make)
  626.         [self ok:0];
  627.     }
  628.     }
  629.  
  630.  
  631. //-----------------------------------------------------------------------------
  632. // -actionClick:
  633. //-----------------------------------------------------------------------------
  634. - (void)actionClick:(id)sender
  635.     {
  636.     }
  637.  
  638.  
  639. //-----------------------------------------------------------------------------
  640. // -actionDblClick:
  641. //    *1* FIXME: Stop this cycle of stupidity!  If we can get a better,
  642. //    more generic subclass to work, that accepts the name of the outlet,
  643. //    the name of the action-variable as part of the constructor, then we
  644. //    should do that.
  645. //-----------------------------------------------------------------------------
  646. - (void)actionDblClick:(id)sender
  647.     {
  648.     int const r = [actionScroll selectedRow];
  649.     if (r >= 0)
  650.     {
  651.     id doc = [NSApp activeDocument];
  652.     id dest = [self virtualDestFor:[NSApp connectDestination]];
  653.     NSString* outletName = [self selectedOutletName];
  654.     id conn = [self connectionForOutlet:outletName];
  655.     if (conn != 0)
  656.         [doc removeConnector:conn];
  657.  
  658.     int const tag = [actionScroll tagAtRow:r column:MISC_TS_CONN_AS];
  659.     if (tag == 0)
  660.         {
  661.         NSString* s = [actionScroll stringValueAtRow:r
  662.                 column:MISC_TS_NAME_AS];
  663.         id realDest = [self realDestFor:dest];
  664.         if ([outletName isEqualToString:@"target"])
  665.         {
  666.         conn = [[NSIBControlConnector alloc]
  667.             initSource:[self object] destination:realDest label:s];
  668.         }
  669.         else
  670.         {
  671.         conn = [[MiscTableConnector alloc]
  672.             initSource:[self object] destination:realDest label:s
  673.             outlet:outletName
  674.             action:[self actionForOutlet:outletName]];
  675.         }
  676.         if (conn != 0)
  677.         {
  678.         [self setCurout:outletName];
  679.         [doc addConnector:conn];
  680.         }
  681.         }
  682.     [self ok:0];
  683.     }
  684.     }
  685.  
  686.  
  687. //-----------------------------------------------------------------------------
  688. // findRowWithTag
  689. //    Find the first row (in visual-order) with the given tag.
  690. //-----------------------------------------------------------------------------
  691. static int findRowWithTag( MiscTableScroll* scroll, int tag )
  692.     {
  693.     unsigned int const lim = [scroll numberOfRows];
  694.     for (unsigned int i = 0; i < lim; i++)
  695.     {
  696.     int const r = [scroll rowAtPosition:i];
  697.     if ([scroll rowTag:r] == tag)
  698.         return r;
  699.     }
  700.     return -1;
  701.     }
  702.  
  703.  
  704. //-----------------------------------------------------------------------------
  705. // -preselectOutlet
  706. //-----------------------------------------------------------------------------
  707. - (NSString*)preselectOutlet
  708.     {
  709.     int row = findRowWithTag( outletScroll, int(curdst) );
  710.     if (row < 0)
  711.     {
  712.     row = findRowWithTag( outletScroll, 0 );
  713.     if (row < 0)
  714.         row = 0;
  715.     }
  716.  
  717.     return [outletScroll stringValueAtRow:row column:MISC_TS_NAME_OS];
  718.     }
  719.  
  720.  
  721. //-----------------------------------------------------------------------------
  722. // -preselect
  723. //-----------------------------------------------------------------------------
  724. - (void)preselect
  725.     {
  726.     if ([outletScroll numberOfRows] > 0)
  727.     {
  728.     id oldsrc = cursrc;
  729.     id olddst = curdst;
  730.     if ([NSApp isConnecting])
  731.         {
  732.         cursrc = [NSApp connectSource];
  733.         curdst = [self virtualDestFor:[NSApp connectDestination]];
  734.         }
  735.     else
  736.         {
  737.         cursrc = [self object];
  738.         curdst = 0;
  739.         }
  740.     
  741.     if (oldsrc != cursrc || olddst != curdst)
  742.         [self setCurout:[self preselectOutlet]];
  743.     
  744.     [self selectOutlet:curout];
  745.     }
  746.     }
  747.  
  748.  
  749. //-----------------------------------------------------------------------------
  750. // -revert:
  751. //-----------------------------------------------------------------------------
  752. - (void)revert:(id)sender
  753.     {
  754.     [super revert:sender];
  755.     [self getConnList];
  756.     [self loadOutlets];
  757.     [self loadActions];
  758.     [self preselect];
  759.     }
  760.  
  761.  
  762. //-----------------------------------------------------------------------------
  763. // -ok:
  764. //-----------------------------------------------------------------------------
  765. - (void)ok:(id)sender
  766.     {
  767.     [super ok:sender];
  768.     [self revert:0];
  769.     }
  770.  
  771.  
  772. //-----------------------------------------------------------------------------
  773. // -wantsButtons
  774. //-----------------------------------------------------------------------------
  775. - (BOOL)wantsButtons
  776.     {
  777.     return NO;
  778.     }
  779.  
  780. @end
  781.