home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / MiscKit1.2.6 / Source / MiscTree.m < prev    next >
Encoding:
Text File  |  1994-01-06  |  4.1 KB  |  148 lines

  1. //
  2. //    MiscTree.m -- a generic class to build tree data structures
  3. //        Written by Don Yacktman (c) 1993 by Don Yacktman.
  4. //                Version 1.0.  All rights reserved.
  5. //
  6. //        This notice may not be removed from this source code.
  7. //
  8. //        This is a free object!  Contact the author for the latest version.
  9. //        Don Yacktman, 4279 N. Ivy Lane, Provo, UT, 84604
  10. //        e-mail:  Don_Yacktman@byu.edu
  11. //
  12. //    This object is included in the MiscKit by permission from the author
  13. //    and its use is governed by the MiscKit license, found in the file
  14. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  15. //    for a list of all applicable permissions and restrictions.
  16. //    
  17.  
  18. #import <misckit/MiscTree.h>
  19. #import <misckit/MiscString.h>
  20. #import <stdio.h>
  21.  
  22. @implementation MiscTree
  23.  
  24. - init            // special init for this class
  25. {
  26.     [self initLabel:""];
  27.     return self;
  28. }
  29.  
  30. - initLabel:(const char *)newLabel
  31. {
  32.     [super init];
  33.     notCollapsed = YES;
  34.     // set up a list class to hold pointers to other Tree objects (branches).
  35.     branches = [[List alloc] init];    // make a dynamic-sized array of objects
  36.     label = [[MiscString alloc] init];    // make a string for the label
  37.     [label setString:newLabel];
  38.     return self;
  39. }
  40.  
  41. - initLabelString:string    // send in a String object
  42. {
  43.     [self init];
  44.     if (label) [label free];
  45.     label = string;
  46.     return self;
  47. }
  48.  
  49. - setLabel:(const char *)newLabel
  50. {
  51.     [label setString:newLabel];
  52.     return self;
  53. }
  54.  
  55. - setValue:newValue
  56. {
  57.     if (value) [value free];
  58.     value = newValue;
  59.     return self;
  60. }
  61.  
  62. - free            // clean up our mess
  63. {
  64.     [branches freeObjects];    // free the branches we're responsible for
  65.     // (I assumed that each branch only has one parent...if that's not
  66.     // the case, then the above line should be axed.)
  67.     [branches free];        // get rid of the List object
  68.     return [super free];
  69. }
  70.  
  71. - addBranch:child    // add a new child node
  72. {    // add to the end of the "branches" List object
  73.     return [branches addObject:child];
  74. }
  75.  
  76. - dumpTree:(NXStream *)file level:(int)lev indent:(const char *)ind
  77. {
  78.     int i; BOOL doKids;
  79.     
  80.     for (i=0; i<lev; i++) NXPrintf(file, "%s", ind);    // indent
  81.     NXPrintf(file, "%s", [label stringValue]);        // and print label
  82.     doKids = [self moreData:file level:lev indent:ind];
  83.     NXPrintf(file, "\n");                           // print newline
  84.     if (doKids)
  85.         for (i=0; i<[branches count]; i++)        // then do children
  86.             [[branches objectAt:i]
  87.              dumpTree:file level:(lev + 1) indent:ind];
  88.     return self;
  89. }
  90.  
  91. - (BOOL)moreData:(NXStream *)file level:(int)lev indent:(const char *)ind
  92. {    // Subclass responsibility -- you can dynamically control collapsing
  93.     // (for example, cut off at a certain level, etc.) and also add info
  94.     // to the end of a dumped node's line from here.  Be sure to message
  95.     // super when you override this method; if this method returns a NO
  96.     // then you should return a NO, regardless.  Don't just use the
  97.     // notCollapsed instance var, since it may change in the future; look
  98.     // at the return value from super!
  99.     //
  100.     // Here's how you might override to keep from printing levels deeper
  101.     // than level 2 (remember that the root level is zero):
  102.     //
  103.     // - (BOOL)moreData:(NXStream *)file level:(int)lev indent:(const char *)ind
  104.     // {
  105.     //     if ((lev > 2) || ![super moreData:file level:lev indent:ind])
  106.     //         return NO;
  107.     //     return YES;
  108.     // }
  109.     //
  110.     return notCollapsed;
  111. }
  112.  
  113. - (int)width
  114. {    // This is recursive, as you will note.
  115.     int num = [branches count];
  116.     int i, count = 0;
  117.     
  118.     if (!num) return 1;    // No children, so we're only one node wide...
  119.     
  120.     // have kids, so sum up their widths.
  121.     for (i=0; i<num; i++) count += [[branches objectAt:i] width];
  122.     return count;
  123. }
  124.  
  125. - (int)depth
  126. {    // This is recursive, as you will note.
  127.     int num = [branches count];
  128.     int i, temp, deepest = 1;
  129.     
  130.     if (!num) return 1;    // No children, so only one node deep
  131.     
  132.     // have kids, so see which branch is deepest.
  133.     for (i=0; i<num; i++) {
  134.         temp = [[branches objectAt:i] depth];
  135.         if (temp > deepest) deepest = temp;
  136.     }
  137.     return (deepest + 1);    // we are one deeper than the deepest child.
  138. }
  139.  
  140. - branches { return branches; }
  141. - collapse { notCollapsed = NO; return self; }
  142. - uncollapse { notCollapsed = YES; return self; }
  143. - (BOOL)collapsed { return !notCollapsed; }
  144. - (const char *)label { return [label stringValue]; }
  145. - (const char *)value { return [value stringValue]; }
  146.  
  147. @end
  148.