home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Temp / QuickProject / Controller.m < prev    next >
Encoding:
Text File  |  1995-04-12  |  8.4 KB  |  354 lines

  1. // Copyright (C) 1995 Steve Hayman
  2. // Use is governed by the MiscKit license
  3.  
  4. #import "Controller.h"
  5. #import <misckit/misckit.h>
  6. #import "MiscViews.subproj/MiscIconWell.h"
  7. #import <stdio.h>
  8.  
  9. @implementation Controller
  10.  
  11. - appDidInit:sender
  12. {
  13.     char bundleTemplates[MAXPATHLEN+1];
  14.     FILE *p;
  15.     MiscString *cmdline = [[MiscString alloc] init];
  16.     MiscString *aFile = [[MiscString alloc] init];
  17.         
  18.     /*
  19.      * Set up some defaults
  20.      */
  21.     static NXDefaultsVector myDefaults = {
  22.     {"OpenInProjectBuilder", "YES"},
  23.     {NULL}
  24.     };
  25.     
  26.     [NXApp registerDefaults:myDefaults];
  27.     
  28.     templateList = [[MiscStringArray alloc] init];
  29.     [templates setDelegate:templateList];
  30.     templatePathnames = [[MiscStringArray alloc] init];
  31.         
  32.     [[NXBundle mainBundle] getPath:bundleTemplates
  33.         forResource:"QuickProjectTemplates" ofType:NULL];
  34.     
  35.     /*
  36.      * Run a simple command to retrieve a list of all the possible
  37.      * project templates.
  38.      * TODO - use a MiscSubprocess here (maybe - might be overkill)
  39.      */
  40.     /*
  41.      * Use ls rather than echo just so we get output files one per line.
  42.      */
  43.     [cmdline catFromFormat:"/bin/ls -d ~/Library/QuickProjectTemplates/* /LocalLibrary/QuickProjectTemplates/* %s/*", bundleTemplates];
  44.     
  45.     
  46.     p = popen([cmdline stringValue], "r");
  47.     
  48.     if ( p ) {
  49.     // read filenames, add to the lists.
  50.     [aFile setStringValue:""];
  51.     while ( [aFile fgets:p keepNewline:NO] != EOF ) {
  52.         
  53.         // Keep a list of full pathnames in templatePathnames;
  54.         // keep a parallel list of filenames in templateList, which
  55.         // is what's displayed in the browser.
  56.         [templatePathnames addString:[aFile stringValue]];
  57.         [templateList addString: 
  58.         [[aFile fileName] stringValueAndFree]];
  59.         
  60.         [aFile setStringValue:""];
  61.     }
  62.     [templates loadColumnZero];
  63.     [self showSelectedPath:templates];
  64.  
  65.     pclose(p);
  66.     } else {
  67.     NXRunAlertPanel([NXApp appName], 
  68.         "Couldn't make list of project templates", NULL,NULL,NULL);
  69.     }
  70.     
  71.     /*
  72.      * And finally, select the Name text as a convenience.
  73.      */
  74.     [name selectText:self];
  75.     
  76.     /*
  77.      * Register to receive TIFF services.   So you can use Grab to get
  78.      * an icon, which we'll make into an image and paste into the
  79.      * icon well.
  80.      */
  81.     {
  82.     const char *returnTypes[2];
  83.     returnTypes[0] = NXTIFFPboardType;
  84.     returnTypes[1] = NULL;
  85.     [NXApp registerServicesMenuSendTypes:NULL andReturnTypes:returnTypes];
  86.     }
  87.     return self;
  88. }
  89.  
  90.  
  91. /*
  92.  * Save the icon, if there is one, to a temporary file and return
  93.  * a MiscString containing its pathname.
  94.  */
  95.  
  96. - saveIconToTempFile
  97. {
  98.     MiscString *filename;
  99.     NXStream *str;
  100.     if ( ! [iconWell image] )
  101.     return nil;
  102.     
  103.     filename = [[MiscString alloc] init];
  104.     [filename catFromFormat:"/tmp/icon%d.tiff", getpid()];
  105.     
  106.     str = NXOpenMemory(NULL, 0L, NX_READWRITE);
  107.     [[iconWell image] writeTIFF:str];
  108.     NXSaveToFile( str, [filename stringValue] );
  109.     NXCloseMemory(str, NX_FREEBUFFER);
  110.     
  111.     return filename;
  112. }
  113. - saveAs:sender
  114. {
  115.     id sp = [SavePanel new];
  116.     MiscString *cmd = [[MiscString alloc] init];
  117.     const char *filename;
  118.     const char *templatePath;
  119.     int pos;
  120.     MiscSubprocess *proc;
  121.     NXBundle *mainBundle = [NXBundle mainBundle];
  122.     id selectionList = [[List alloc] init];
  123.     MiscString *iconFileName;
  124.     
  125.     if ( ! [name stringValue] || (strlen([name stringValue]) == 0) ) {
  126.     NXRunAlertPanel([NXApp appName],
  127.         "Please supply a name for your project.",
  128.         NULL,NULL,NULL);
  129.     return nil;
  130.     }
  131.     
  132.     
  133.     if ( [sp runModalForDirectory:NULL file: [name stringValue]] ) {
  134.     filename = [sp filename];
  135.     destinationFile = [MiscString newWithString:filename];
  136.     
  137.     // Save the icon image - if there is one - in a file so that
  138.     // we can pass its pathname to copy_project.
  139.     
  140.     iconFileName = [self saveIconToTempFile];
  141.  
  142.     // Now copy the chosen project.  Figure out the index of
  143.     // the selected cell, and ask the templateList for the full
  144.     // string value at that position -not just the basename 
  145.     // displayed in the browser    
  146.     pos = [[templates matrixInColumn:0] selectedRow];
  147.     templatePath = [templatePathnames stringAt:pos];
  148.     
  149.     // copy_project  template_dir dest_dir template_name appname
  150.     
  151.     [cmd sprintf:"%s/copy_project %s %s %s %s %s", 
  152.         [mainBundle directory],
  153.         templatePath,
  154.         [sp filename],
  155.         [templates stringValue],
  156.         [name stringValue],
  157.         iconFileName ? [iconFileName stringValue] : ""];
  158.  
  159.     
  160.  
  161.     [iconFileName free];
  162.         
  163.     /*
  164.      * Fire up a MiscSubprocess object to execute the copy command.
  165.      */
  166.  
  167.     proc = [[MiscSubprocess alloc]
  168.         init:[cmd stringValue]
  169.         withDelegate:self];
  170.     }
  171.     [cmd free];
  172.     [selectionList free];
  173.     return self;
  174.  
  175. }
  176. /*
  177.  * This is the target of the browser.   The browser shows only the
  178.  * basename of the project template you've chosen; display its full
  179.  * path as well.  (Except we replace the home directory with "~" since it
  180.  * takes up less space on the screen.)
  181.  */
  182.  
  183. - showSelectedPath:sender
  184. {
  185.     int selection = [[sender matrixInColumn:0] selectedRow];
  186.     id templatePath = [MiscString newWithString: [templatePathnames stringAt:selection]];
  187.     
  188.     [templatePath replaceHomeWithTilde];    // looks nicer. less room too.
  189.     [selectedTemplatePath
  190.         setStringValue: [templatePath stringValueAndFree]];
  191.     return self;
  192. }
  193.  
  194.  
  195. /*
  196.  * Subprocess delegate methods
  197.  */
  198. - subprocess:sender done:(int)status :(MiscSubprocessEndCode)code
  199. {
  200.     MiscString *projectFile;
  201.     [sender terminate:self];
  202.     [sender free];
  203.     
  204.     if ( code == Misc_Exited && status == 0 ) {
  205.     /*
  206.      * message Workspace here to open the PB.project
  207.      */
  208.     
  209.     
  210.     
  211.     if ( [NXApp defaultBoolValue:"OpenInProjectBuilder"] ) {
  212.     
  213.         /*
  214.         * Figure out the path to the PB.project file
  215.         */
  216.         projectFile = [destinationFile copy];
  217.         [projectFile cat:"/PB.project"];
  218.  
  219.         [[[self log:"Opening project file "]
  220.         log:[projectFile stringValue]]
  221.         log:"\n"];
  222.  
  223.         [[Application workspace] openFile:[projectFile stringValue]];
  224.         [projectFile free];
  225.     }
  226.     NXRunAlertPanel([NXApp appName],
  227.         "Project created succesfully.", "OK", NULL, NULL);
  228.     }
  229.     return self;
  230. }
  231. - subprocess:sender output:(const char *) buffer
  232. {
  233.     [self log:buffer];
  234.  
  235.     return self;
  236. }
  237. - subprocess:sender stderrOutput:(const char *)buffer
  238. {
  239.     [self log:buffer];
  240.     return self;
  241. }
  242. - subprocess:sender error:(const char *)errorString
  243. {
  244.     [self log:"Error: "];
  245.     [self log:errorString];
  246.  
  247.     return self;
  248. }
  249.  
  250. - log:(const char *)str
  251. {
  252.     int len;
  253.     if ( ! processLog ) 
  254.     [NXApp loadNibSection:"SubprocessLog.nib" owner:self];
  255.     len = [processLog textLength];
  256.     [processLog setSel:len:len];
  257.     [processLog replaceSel:str];
  258.     [processLog scrollSelToVisible];
  259.     [[processLog window] makeKeyAndOrderFront:self];
  260.     return self;
  261. }
  262.  
  263. /*
  264.  * Preferences handling
  265.  */
  266.  
  267. - showPreferences:sender
  268. {
  269.     if ( ! prefsPanel ) {
  270.     [NXApp loadNibSection:"Preferences.nib" owner:self];
  271.     [openInPBSwitch setState: 
  272.         [NXApp defaultBoolValue:"OpenInProjectBuilder"]];
  273.     }
  274.     
  275.     [self revert:self];
  276.     [prefsPanel makeKeyAndOrderFront:self];
  277.     return self;
  278. }
  279.  
  280. - ok:sender
  281. {
  282.     [NXApp setBoolDefault:"OpenInProjectBuilder" to: [openInPBSwitch state]];
  283.     
  284.     return self;
  285. }
  286.  
  287. - revert:sender
  288. {
  289.     [openInPBSwitch setState: [NXApp defaultBoolValue:"OpenInProjectBuilder"]];
  290.     
  291.     return self;
  292. }
  293.  
  294.  
  295. /*
  296.  * A couple of methods that support doing Services -> Grab
  297.  * so we can pick up a tiff and use it as our icon
  298.  */
  299.  
  300. - validRequestorForSendType:(NXAtom)typeSent
  301.                         andReturnType:(NXAtom)typeReturned
  302. {
  303.     if ( typeSent == NULL && typeReturned == NXTIFFPboardType )
  304.     return self;
  305.     return nil;
  306. }
  307.  
  308. - readSelectionFromPasteboard:pb
  309. {
  310.     id image = [[NXImage alloc] initFromPasteboard:pb];
  311.     /*
  312.      * what we should do here is save the image to a temp file,
  313.      * and tell the icon well that that's the filename.
  314.      * but this is quicker for now even though not what we want.
  315.      */
  316.     [iconWell setImage: image];
  317.     return self;
  318. }
  319.  
  320. /*
  321.  * Some more methods that allow pasting a TIFF selection.
  322.  */
  323.  
  324. - paste:sender
  325. {
  326.     id pb = [Pasteboard new];
  327.     BOOL tiffFound = NO;
  328.     const NXAtom *types;
  329.     NXImage *pasteImage;
  330.     
  331.     types = [pb types];
  332.     /*
  333.      * is there TIFF on the pasteboard?
  334.      */
  335.     if ( types ) {
  336.     while ( *types ) {
  337.         if ( *types++ == NXTIFFPboardType ) {
  338.         tiffFound = YES;
  339.         break;
  340.         }
  341.     }
  342.     }
  343.  
  344.     if ( ! tiffFound )
  345.     return nil;
  346.     
  347.     pasteImage = [[NXImage alloc] initFromPasteboard:pb];
  348.     [iconWell setImage: pasteImage];    // don't free it. iconwell keeps it.
  349.     
  350.     return self;
  351. }
  352.  
  353. @end
  354.