home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1994 June / NEBULA_SE.ISO / SourceCode / Palettes / MORegex / MORegexFormCellInspector.m < prev    next >
Encoding:
Text File  |  1993-10-02  |  8.0 KB  |  309 lines

  1. // MORegexFormCellInspector.h
  2. //
  3. // by Mike Ferris
  4. // Part of MOKit - MORegexPalette
  5. // Copyright 1993, all rights reserved.
  6.  
  7. #import "MORegexFormCellInspector.h"
  8. #import "MOKit/MORegexFormCell.h"
  9. #import "MOKit/MOString.h"
  10. #import <objc/objc-runtime.h>
  11.  
  12. #define CLASS_VERSION    0
  13.  
  14. #define ADD_TAG            0
  15. #define CHANGE_TAG        1
  16. #define REMOVE_TAG        2
  17.  
  18. #define BUNDLE_TYPE                            "bundle"
  19. #define MOREGEXFORMCELL_CLASS_NAME            "MORegexFormCell"
  20.  
  21. #define NIB_TYPE                            "nib"
  22. #define NIB_NAME                            "MORegexFormCellInspector"
  23.  
  24. @implementation MORegexFormCellInspector
  25.  
  26. static id MORegexFormCellClass;
  27.  
  28. + MO_loadClassBundle:(const char *)className
  29. // Finds the bundle of the same name as the class, grabs it and loads the
  30. // class from it.
  31. {
  32.     char pathBuff[MAXPATHLEN+1];
  33.     
  34.     // Load the bundle
  35.     if (objc_lookUpClass(className) == nil)  {
  36.         // class is not already loaded... load it.
  37.         id classBundle;
  38.         
  39.         // Look for the bundle in the main bundle first, 
  40.         // else try in this classes bundle.
  41.         if (![[NXBundle mainBundle] getPath:pathBuff forResource:className 
  42.                     ofType:BUNDLE_TYPE])  {
  43.             if (![[NXBundle bundleForClass:[self class]] getPath:pathBuff 
  44.                         forResource:className ofType:BUNDLE_TYPE])  {
  45.                 NXLogError("[MORegexPalette loadClassBundle] failed to "
  46.                         "find %s class bundle.", className);
  47.                 return nil;
  48.             }
  49.         }
  50.         classBundle = [[NXBundle allocFromZone:[self zone]] 
  51.                     initForDirectory:pathBuff];
  52.         if (!classBundle)  {
  53.             NXLogError("[MORegexPalette loadClassBundle] failed to "
  54.                         "create bundle for class %s.", className);
  55.             return nil;
  56.         }
  57.         if (![classBundle classNamed:className])  {
  58.             NXLogError("[MORegexPalette loadClassBundle] failed to "
  59.                         "load %s class from bundle.", className);
  60.             return nil;
  61.         }
  62.     }
  63.     
  64.     return self;
  65. }
  66.  
  67. + initialize
  68. // Set the version.
  69. {
  70.     if (self == [MORegexFormCellInspector class])  {
  71.         [self setVersion:CLASS_VERSION];
  72.  
  73.         // Load the MORegexFormCell class if necessary
  74.         if ((MORegexFormCellClass = 
  75.                     objc_lookUpClass(MOREGEXFORMCELL_CLASS_NAME)) == nil)  {
  76.             [self MO_loadClassBundle:MOREGEXFORMCELL_CLASS_NAME];
  77.             MORegexFormCellClass = 
  78.                         objc_lookUpClass(MOREGEXFORMCELL_CLASS_NAME);
  79.             if (!MORegexFormCellClass)  {
  80.                 NXLogError("[MORegexFormCell initialize]: failed to find "
  81.                             "MORegexFormCell class.");
  82.             }
  83.         }
  84.     }
  85.     return self;
  86. }
  87.  
  88. - init
  89. // Load our nib file.
  90. {
  91.     char buf[MAXPATHLEN+1];
  92.     id bundle;
  93.     
  94.     [super init];
  95.     
  96.     // load our nib file.
  97.     bundle = [NXBundle bundleForClass:[MORegexFormCellInspector class]];
  98.     [bundle getPath:buf forResource:NIB_NAME ofType:NIB_TYPE];
  99.     [NXApp loadNibFile:buf owner:self withNames:NO fromZone:[self zone]];
  100.     
  101.     [patternText setDelegate:self];
  102.     [patternText setCharFilter:NXFieldFilter];
  103.     [patternText setFont:[Font userFixedPitchFontOfSize:0 
  104.                 matrix:NX_FLIPPEDMATRIX]];
  105.     
  106.     return self;
  107. }
  108.  
  109. - (int)browserSelectedRow
  110. // Return the row that is selected in the patternBrowser or -1 if none is.
  111. {
  112.     return [[patternBrowser matrixInColumn:0] selectedRow];
  113. }
  114.  
  115. - (const char *)getPatternText
  116. {
  117.     static char *text=NULL;
  118.     
  119.     if (text) NX_FREE(text);
  120.     NX_MALLOC(text, char, [patternText byteLength]+1);
  121.     [patternText getSubstring:text start:0 length:[patternText textLength]+1];
  122.     return text;
  123. }
  124.  
  125. - enablePatternButtons
  126. // Enables or disables the add, change, remove buttons as appropriate for
  127. // the current state of the inspector.
  128. {
  129.     if ([self browserSelectedRow] == -1)  {
  130.         [[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:NO];
  131.         [[patternButtonMatrix cellAt:0 :REMOVE_TAG] setEnabled:NO];
  132.     }  else  {
  133.         [[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:YES];
  134.         [[patternButtonMatrix cellAt:0 :REMOVE_TAG] setEnabled:YES];
  135.     }
  136.     
  137.     if (strlen([self getPatternText])>0)  {
  138.         [[patternButtonMatrix cellAt:0 :ADD_TAG] setEnabled:YES];
  139.     }  else  {
  140.         [[patternButtonMatrix cellAt:0 :ADD_TAG] setEnabled:NO];
  141.         [[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:NO];
  142.     }
  143.     return self;
  144. }
  145.  
  146. - browserAction:sender
  147. // Copies the string of the currently selected pattern to the pattern text
  148. // field for editing.
  149. {
  150.     int row = [self browserSelectedRow];
  151.     
  152.     // put the text of the selected row's pattern in the patternField.
  153.     if (row >= 0)  {
  154.         [patternText setText:[object regexStrAt:row]];
  155.     }  else  {
  156.         [patternText setText:""];
  157.     }
  158.     [patternText sizeToFit];
  159.     [patternText setSel:0 :[patternText textLength]];
  160.     [self enablePatternButtons];
  161.     return self;
  162. }
  163.  
  164. - patternButtonAction:sender
  165. // Adds the text of patternField to the cell's patterns, or changes the pattern
  166. // currently selected in the patternBrowser to the text in patternField, or 
  167. // removes the pattern in the selected row of the patternBrowser from the
  168. // cell's patterns.
  169. {
  170.     int tag = [[sender selectedCell] tag];
  171.     const char *pattern = [self getPatternText];
  172.     char *pcpy;
  173.     int row = [self browserSelectedRow];
  174.     id matrix = [patternBrowser matrixInColumn:0];
  175.     
  176.     NX_MALLOC(pcpy, char, strlen(pattern)+1);
  177.     strcpy(pcpy, pattern);
  178.     
  179.     if (tag==ADD_TAG)  {
  180.         // add the string in patternField to the object's patterns.
  181.         if (![MORegexFormCellClass isValidRegex:pattern])  {
  182.             NXRunAlertPanel("Regexp Error", "'%s' is not a valid regular "
  183.                         "expression.", "OK", NULL, NULL, pattern);
  184.             NX_FREE(pcpy);
  185.             return self;
  186.         }
  187.         [object addRegexStr:pattern];
  188.     }  else if (tag==CHANGE_TAG)  {
  189.         // change the pattern at the index of the selected row in the 
  190.         // browser to the string in patternField.
  191.         id string = [[object regexStrList] objectAt:row];
  192.         if (![MORegexFormCellClass isValidRegex:pattern])  {
  193.             NXRunAlertPanel("Regexp Error", "'%s' is not a valid regular "
  194.                         "expression.", "OK", NULL, NULL, pattern);
  195.             NX_FREE(pcpy);
  196.             return self;
  197.         }
  198.         [string setStringValue:pattern];
  199.     }  else if (tag==REMOVE_TAG)  {
  200.         // remove the pattern at the index of the selected row in the browser.
  201.         [object removeRegexStrAt:row];
  202.         NX_FREE(pcpy);
  203.         pcpy = NULL;
  204.         pattern = [[matrix cellAt:((row==0)?1:row-1) :0] stringValue];
  205.         if (pattern)  {
  206.             NX_MALLOC(pcpy, char, strlen(pattern)+1);
  207.             strcpy(pcpy, pattern);
  208.         }
  209.     }
  210.     [patternBrowser reloadColumn:0];
  211.     if (pcpy)  {
  212.         char *buff;
  213.         NX_MALLOC(buff, char, strlen(pcpy)+2);
  214.         sprintf(buff, "/%s", pcpy);
  215.         [patternBrowser setPath:buff];
  216.         NX_FREE(buff);
  217.     }
  218.     NX_FREE(pcpy);
  219.     [self browserAction:patternBrowser];
  220.     
  221.     [self enablePatternButtons];
  222.     [self touch:self];
  223.     
  224.     return self;
  225. }
  226.  
  227.  
  228. - ok:sender
  229. // set the tag and enabled flag.  The patternButtonAction takes care of the
  230. // other stuff.
  231. {
  232.     [object setTag:[tagForm intValueAt:0]];
  233.     [object setEnabled:![[checkboxMatrix cellAt:0:0] state]];
  234.     [object setAllowEmptyString:[[checkboxMatrix cellAt:1:0] state]];
  235.     return [super ok:sender];
  236. }
  237.  
  238. - revert:sender
  239. // fill in the inspector with the attributes of "object"
  240. {
  241.     id matrix;
  242.     
  243.     [checkboxMatrix setState:![object isEnabled] at:0:0];
  244.     [checkboxMatrix setState:[object doesAllowEmptyString] at:1:0];
  245.     [tagForm setIntValue:[object tag] at:0];
  246.     
  247.     // browser
  248.     [patternBrowser loadColumnZero];
  249.     
  250.     matrix = [patternBrowser matrixInColumn:0];
  251.     if ([matrix cellCount] > 0)  {
  252.         const char *pattern = [[matrix cellAt:0:0] stringValue];
  253.         char *buff;
  254.         NX_MALLOC(buff, char, strlen(pattern)+2);
  255.         sprintf(buff, "/%s", pattern);
  256.         [patternBrowser setPath:buff];
  257.         NX_FREE(buff);
  258.     }
  259.     [self browserAction:patternBrowser];
  260.     
  261.     [self enablePatternButtons];
  262.     [patternButtonMatrix display];
  263.     
  264.     return [super revert:sender];
  265. }
  266.  
  267. - (BOOL)wantsButtons
  268. // Our inspector does not have OK or Revert buttons.
  269. {
  270.     return NO;
  271. }
  272.  
  273. - (int)browser:sender fillMatrix:matrix inColumn:(int)column
  274. // Fill the browser with the pattern strings from the cell.
  275. {
  276.     int i, c = [object regexStrCount];
  277.     
  278.     for (i=0; i<c; i++)  {
  279.         [matrix renewRows:i+1 cols:1];
  280.         [[matrix cellAt:i :0] setStringValue:[object regexStrAt:i]];
  281.         [[matrix cellAt:i :0] setLoaded:YES];
  282.         [[matrix cellAt:i :0] setLeaf:YES];
  283.     }
  284.     
  285.     return i;
  286. }
  287.  
  288. - textDidGetKeys:sender isEmpty:(BOOL)flag
  289. // Having text in the patternField affects what buttons to enable.
  290. {
  291.     if (sender==patternText)  {
  292.         [self enablePatternButtons];
  293.         [patternButtonMatrix display];
  294.     }
  295.     return self;
  296. }
  297.  
  298. - textDidChange:sender;
  299. // The patternField shouldn't be passed on.
  300. {
  301.     if (sender==patternText)  {
  302.         return self;
  303.     }  else  {
  304.         return [super textDidChange:sender];
  305.     }
  306. }
  307.  
  308. @end
  309.