home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.bin / SourceCode / Starter / Source / Controller.m < prev    next >
Encoding:
Text File  |  1995-02-13  |  7.6 KB  |  390 lines

  1.  
  2. #import "Controller.h"
  3. #import "Document.h"
  4. #import "InspectorManager.h"
  5. #import "defs.h"
  6. #import "util.h"
  7.  
  8. @implementation Controller
  9.  
  10. /* ==== init section ==== */
  11. + initialize
  12. {
  13.     static NXDefaultsVector appDefaults=
  14.     { { "DEBUGFILE", "~/debugfile" },
  15.       { "WindowSize", "400 300" },
  16.       { "NewEmptyDocument", "YES" },
  17.       { (char *)NULL},
  18.     };
  19.     NXRegisterDefaults([NXApp appName], appDefaults);
  20.     return self;
  21. }
  22.  
  23. - init
  24. {    [super init];
  25.     controllerZone=NXCreateZone(vm_page_size, vm_page_size, NO);
  26.     return self;
  27. }
  28.     
  29. - appDidInit:sender
  30. {
  31. id w;
  32.  
  33.     docList=[[List allocFromZone:controllerZone] init];
  34.     
  35.     w=[accessoryView window];
  36.     [accessoryView removeFromSuperview];
  37.     [w free];
  38.  
  39.     if(!fileName && BoolValueForDefault("NewEmptyDocument"))
  40.                 [self newDocument:nil];
  41.     
  42.     return self;
  43. }
  44.  
  45. /* ==== document management section ==== */
  46.  
  47. - openFile:sender
  48. {
  49. static const char *const Filetypes[]=EXTENSION_STRINGS;  
  50. const char *name=NULL;
  51.  
  52.     if(sender)
  53.     {    if ([[OpenPanel new] runModalForTypes: Filetypes]==NO) 
  54.             return (self);
  55.         else 
  56.             if(!(name=[[OpenPanel new] filename]))
  57.             { fprintf(stderr,"Failed to find file: %s\n",
  58.                 [[OpenPanel new] filename]);
  59.                 return self;
  60.             }
  61.     }
  62.     else name=fileName; //opened through the workspace
  63.     
  64.     [self openDocument:name];
  65.     
  66.     /* fileName is handed off to the document object */
  67.     if(fileName) 
  68.       { free((char *)fileName); 
  69.         fileName=NULL;
  70.       }
  71.     return self;
  72. }
  73.  
  74. - createDocumentObject:sender
  75. {    
  76. NXZone *zone;
  77. Document *doc;
  78. static int documentTag=0;
  79.  
  80.     zone=NXCreateZone(vm_page_size*1024, vm_page_size, YES);
  81.     
  82.     /* allocate a new document object */
  83.     doc=[[Document alloc] init];
  84.     
  85.     if(!doc)
  86.      {    internalError("Could not allocate document object");
  87.          return nil;
  88.      }
  89.  
  90.     /* this section opens the document file */
  91.     [doc setTag:documentTag++];
  92.     [NXApp perform:@selector(updateWindows) with:nil
  93.        afterDelay:1 cancelPrevious:YES];
  94.  
  95.     /* put the object on the list of documents */
  96.     [docList addObject:doc];
  97.     return doc;
  98. }
  99.  
  100. - openDocument:(const char *)aPath
  101. {
  102. id doc;
  103.     
  104.     if(!aPath) return nil;
  105.  
  106.     if((doc=[self findDocWithPath:aPath])!=nil)
  107.      {    [[doc window] makeKeyAndOrderFront:nil];
  108.         return nil;
  109.      }
  110.     
  111.     doc=[self createDocumentObject:self];
  112.  
  113.     if(![doc openDocFile:aPath])
  114.      {    [[NXApp delegate] perform:@selector(freeDoc:) with:doc
  115.          afterDelay:1 cancelPrevious:YES];
  116.         return nil;
  117.      }
  118.  
  119.     return doc;
  120. }
  121.  
  122. - newDocument:sender
  123. {    
  124. char buf[BUFSIZE]="";
  125. id new;
  126. static int untitledCount=0;
  127.  
  128.     do { if(untitledCount)
  129.           { sprintf(buf,"%s/UNTITLED%d",NXHomeDirectory(), untitledCount);
  130.           }
  131.          else sprintf(buf,"%s/UNTITLED",NXHomeDirectory());
  132.          untitledCount++;
  133.        } while([self findDocWithPath:buf]);
  134.     new=[self createDocumentObject:self];
  135.     [new setupNewDoc:buf];
  136.     return self;
  137. }
  138.     
  139. - save:sender;
  140. {    
  141. const char *name=[currentDoc documentName];
  142.     if(!name) return self;
  143.  
  144.     if(!strncmp(name,"UNTITLED",8))
  145.               [self saveAs:sender];
  146.     else    [currentDoc saveDocument];
  147.     return self;
  148. }
  149.  
  150. - saveAs:sender
  151. {
  152. const char *file;
  153. char name[1024];
  154. id savePanel;
  155.  
  156.     if(!currentDoc) return self;
  157.     savePanel=[SavePanel new];
  158.     [savePanel setAccessoryView:nil];
  159.     if ([savePanel runModal]) 
  160.        file = [[SavePanel new] filename];
  161.     else return self;   
  162.  
  163.     if (file) 
  164.       { strcpy(name,file);
  165.         insertExt(name, DOC_EXTENSION);
  166.         [currentDoc saveDocumentAs:name];
  167.       }
  168.     
  169.     return self;
  170. }
  171.  
  172. - saveTo:sender;
  173. {
  174. const char *file;
  175. char name[1024];
  176. id savePanel;
  177.  
  178.     if(!currentDoc) return self;
  179.     savePanel=[SavePanel new];
  180.  
  181.     [savePanel setAccessoryView:accessoryView];
  182.     if ([savePanel runModal]) 
  183.        file = [[SavePanel new] filename];
  184.     else return self;   
  185.  
  186.     if (file) 
  187.       { /* insert the needed extension if not there */
  188.         strcpy(name,file);
  189.         [currentDoc saveDocumentAs:name];
  190.       }
  191.     return self;
  192. }
  193.  
  194. - saveAll:sender
  195. {    return self;
  196. }
  197.  
  198. - revert:sender
  199. {
  200. id doc=currentDoc;
  201.  
  202.     if(!doc) return self;
  203.     
  204.     /* clear the inspector */
  205.     currentDoc=nil;
  206.     [inspectorManager updateInspector:self];
  207.     [docList removeObject:doc];
  208.     
  209.     if(!strcmp([doc documentName],"UNTITLED"))
  210.      { NXRunAlertPanel("Revert",
  211.          "Document does not have a name, cannot revert...",NULL,NULL,NULL);
  212.        return self;
  213.      }
  214.     /* this will set the new doc to be the currentdoc */
  215.     currentDoc=[self openDocument:[doc documentPath]];
  216.     
  217.     /* this will free the old one */
  218.     [[doc window] setDocEdited:NO];
  219.     [[doc window] performClose:self];
  220.  
  221.     return self;
  222. }
  223.  
  224. - close:sender
  225. {    if(!currentDoc) return self;
  226.     return [[currentDoc window] performClose:nil];
  227. }
  228.  
  229. - freeDoc:aDoc
  230. {
  231.     if(!aDoc) return nil;
  232.     
  233.     [docList removeObject:aDoc];
  234.     
  235.     if(currentDoc==aDoc)  currentDoc=nil;
  236.     [NXApp delayedFree:aDoc];
  237.  
  238.     [NXApp perform:@selector(updateWindows) with:nil
  239.        afterDelay:100 cancelPrevious:YES];
  240.  
  241.     return self;
  242. }
  243.  
  244. - findDocWithPath:(const char *)aPath
  245. {
  246. id *l;
  247. int i,count;
  248. const char *p;
  249.  
  250.     count=[docList count];
  251.     l=NX_ADDRESS(docList);
  252.     for(i=0;i<count;i++)
  253.      {     p=[l[i] documentPath];
  254.           if(p && !strcmp(aPath,p)) return l[i];
  255.      }
  256.     return nil;
  257. }
  258.  
  259. - findDocWithTag:(int)aTag
  260. {
  261. id *l;
  262. int i,count;
  263.  
  264.     count=[docList count];
  265.     l=NX_ADDRESS(docList);
  266.     for(i=0;i<count;i++)
  267.       { if([l[i] tag]==aTag) return l[i];
  268.       }
  269.     return nil;
  270. }
  271.  
  272. /* ==== panels ==== */
  273.  
  274. - getPrefsPanel:sender
  275. {
  276.     if(!prefManager)
  277.       [NXApp  loadNibSection:"PrefPanel.nib" owner:self
  278.        withNames:NO fromZone:controllerZone];
  279.     [prefManager getPanelWithScreen:0];
  280.     return self;
  281. }
  282.  
  283. - getInspectorPanel:sender
  284. {
  285.     /* called from the menu */
  286.     [self getInspectorPanelWithScreen:0];
  287.     return self;
  288. }
  289.  
  290. - (BOOL)getInspectorPanelWithScreen:(int)aScreen
  291. {
  292.     /* called from the keyboard */
  293.     if(aScreen<0 || aScreen>1) return NO;
  294.     if(!inspectorManager)
  295.       [NXApp  loadNibSection:"InspectorPanel.nib" owner:self
  296.        withNames:NO fromZone:controllerZone];
  297.     [inspectorManager getPanelWithScreen:aScreen];
  298.     return YES;
  299. }
  300.  
  301. - getInfoPanel:sender
  302. {
  303.     if(!infoPanel)
  304.       [NXApp  loadNibSection:"InfoPanel.nib" owner:self
  305.        withNames:NO fromZone:controllerZone];
  306.     [infoPanel makeKeyAndOrderFront:nil];
  307.     return self;
  308. }
  309.  
  310. /* ==== access to instance variables ==== */
  311.  
  312. /* the current document always point to the document object
  313.    corresponding to the current window
  314.  */
  315.  
  316. - setCurrentDoc:aDoc
  317. {    currentDoc=aDoc;
  318.     return self;
  319. }
  320.  
  321. - currentDoc
  322. {    return currentDoc;
  323. }
  324.  
  325.     
  326. /* ==== application delegate methods ==== */
  327.  
  328. - (BOOL)appAcceptsAnotherFile:sender
  329. {
  330.     return YES;
  331. }
  332.  
  333. - (int)appOpenFile:(const char *)path type:(const char *)type
  334. {
  335.  
  336.     if(strncmp(type, DOC_EXTENSION, strlen(DOC_EXTENSION))) return NO;
  337.     fileName=NXCopyStringBufferFromZone(path, controllerZone);
  338.          
  339.     [self perform:@selector(openFile:) with:nil afterDelay:1
  340.         cancelPrevious: NO];  
  341.     return YES;
  342. }
  343.  
  344. - appWillTerminate:sender
  345. {
  346. int i,count=[docList count];
  347. BOOL needsWarning=NO;
  348. id doc,*l=NX_ADDRESS(docList);
  349.  
  350. TRY_AGAIN:
  351.     doc=currentDoc;
  352.     for(i=0;i<count;i++)
  353.      { if([[l[i] window] isDocEdited]) needsWarning=YES;
  354.      }
  355.     if(needsWarning)
  356.      { switch(NXRunAlertPanel("Quit",
  357.           "There are edited documents",
  358.           "Review Unsaved","Quit Anyway","Cancel"))
  359.            { case NX_ALERTDEFAULT: // Review Unsaved
  360.               
  361.               for(i=0;i<count;i++)
  362.                { if([[l[i] window] isDocEdited])
  363.                   { switch(NXRunAlertPanel("Review Unsaved",
  364.                     "Save changes to %s","Save","Don't save",
  365.                     "Cancel",[l[i] documentPath]))
  366.                      { case NX_ALERTDEFAULT: //Save
  367.                         currentDoc=l[i];
  368.                         [[l[i] window] orderFront:nil];
  369.                         [self save:self];
  370.                         currentDoc=doc;
  371.                         break;
  372.                        case NX_ALERTALTERNATE: //Don't save
  373.                             break;
  374.                        case NX_ALERTOTHER: //Cancel
  375.                             goto TRY_AGAIN;
  376.                      }
  377.                   }
  378.                }
  379.              case NX_ALERTALTERNATE: //Quit Anyway
  380.                                      break;
  381.              case NX_ALERTOTHER: //Cancel
  382.                                   return nil;
  383.            }
  384.      }
  385.  
  386.     return self;
  387. }
  388.  
  389. @end
  390.