home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer) / NeXT_Developer-3.3.iso / NextDeveloper / Examples / AppKit / Graph / GraphApp.m < prev    next >
Encoding:
Text File  |  1993-07-19  |  7.8 KB  |  261 lines

  1.  
  2. /*
  3.     GraphApp.m
  4.  
  5.     GraphApp is the delegate of the Application object.  It deals with opening
  6.     new documents as initiated by the menu commands or messages from the
  7.     Workspace Manager.
  8.  
  9.     You may freely copy, distribute, and reuse the code in this example.
  10.     NeXT disclaims any warranty of any kind, expressed or implied, as to its
  11.     fitness for any particular use.
  12. */
  13.  
  14. #import "Graph.h"
  15.  
  16. static Window *findDocWindow(const char *name);
  17.  
  18. @implementation GraphApp
  19.  
  20. - appDidInit:sender {
  21.   /*
  22.    * If we weren't asked to open any documents at launch time, then we were
  23.    * launched by double clicking on the application instead of a document.
  24.    * In this case, we open up a new document for the user.
  25.    */
  26.     if (!NXGetDefaultValue([NXApp appName], "NXOpen") &&
  27.     !NXGetDefaultValue([NXApp appName], "NXOpenTemp") &&
  28.     !NXGetDefaultValue([NXApp appName], "NXServiceLaunch"))
  29.     [self new3D:self];
  30.     return self;
  31. }
  32.  
  33. /*
  34.  * Called as we are quitting.  Gives the user a change to save unsaved work.
  35.  * The Draw example has a more complete implementation of this, since it does
  36.  * not give the user the "Cancel" option when logging out or powering off.
  37.  */
  38. - appWillTerminate:sender {
  39.     int response;
  40.     List *windowList = [NXApp windowList];
  41.     int count;
  42.     Window *window;
  43.     BOOL dirtyDocs = NO;
  44.     id document;
  45.     NXStringTable *stringTab;
  46.  
  47.     count = [windowList count];
  48.     while (count--) {
  49.     if ([[windowList objectAt:count] isDocEdited]) {
  50.         dirtyDocs = YES;
  51.         break;
  52.     }
  53.     }
  54.     if (dirtyDocs) {
  55.     stringTab = [self stringTable];
  56.     response =  NXRunAlertPanel([stringTab valueForStringKey:"quit alert title"],
  57.             [stringTab valueForStringKey:"quit alert message"],
  58.             [stringTab valueForStringKey:"review button"],
  59.             [stringTab valueForStringKey:"quit button"],
  60.             [stringTab valueForStringKey:"cancel button"]);
  61.     if (response == NX_ALERTALTERNATE)  {
  62.         return self;
  63.     } else if (response == NX_ALERTOTHER)  {
  64.         return nil;
  65.     } else {
  66.         count = [windowList count];
  67.         while (count--) {
  68.         window = [windowList objectAt:count];
  69.         document = [window delegate];
  70.         if ([document isKindOfClassNamed:"GraphDoc"] || [document isKindOfClassNamed:"Graph3DDoc"]) {
  71.             if (![document windowWillClose:sender]) {
  72.             return nil;
  73.             }
  74.         }
  75.         }
  76.         return self;
  77.     }
  78.     } else {
  79.     return self;
  80.     }
  81. }
  82.  
  83. /*
  84.  * This method is performed whenever a user double-clicks on an icon in
  85.  * the Workspace Manager representing a Draw program document.  If the file
  86.  * is already open, it just orders its window to the front; else, it opens
  87.  * a new graph document from the file.
  88.  */
  89. - (int)app:sender openFile:(const char *)path type:(const char *)type {
  90.     BOOL success = NO;
  91.     Window *win;
  92.     NXStringTable *stringTab;
  93.  
  94.     if (type) {
  95.     if (win = findDocWindow(path)) {
  96.         [win makeKeyAndOrderFront:self];
  97.         success = YES;
  98.     } else if (!strcmp(type, "xygraph")) {
  99.         if ([[GraphDoc allocFromZone:[self zone]] initFromFile:path])
  100.         success = YES;
  101.     } else if (!strcmp(type, "xyzgraph")) {
  102.         if ([[Graph3DDoc allocFromZone:[self zone]] initFromFile:path])
  103.         success = YES;
  104.     }
  105.     }
  106.     if (!success) {
  107.     stringTab = [self stringTable];
  108.     NXRunAlertPanel(
  109.             [stringTab valueForStringKey:"open alert title"],
  110.             [stringTab valueForStringKey:"open alert message"],
  111.             [stringTab valueForStringKey:"ok button"],
  112.             NULL, NULL, path);
  113.     }
  114.     return success;
  115. }
  116.  
  117. /* This says we can accept any number of app:openFile:type: messages. */
  118. - (BOOL)appAcceptsAnotherFile:sender {
  119.     return YES;
  120. }
  121.  
  122. /* action method, called when the user chooses open in the menu */
  123. - open:sender {
  124.     const char *const *files;
  125.     static const char *const fileType[3] = {"xygraph", "xyzgraph", NULL};
  126.     OpenPanel *openPanel;
  127.     char fullName[MAXPATHLEN];
  128.     const char *suffix;
  129.  
  130.   /*
  131.    * Declare that the user can select multiple files to be opened in the
  132.    * Open Panel.  All apps should do this, since its so easy.
  133.    */
  134.     openPanel = [[OpenPanel new] allowMultipleFiles:YES];
  135.  
  136.   /* run the open panel, filtering for out types of our documents */
  137.     if ([openPanel runModalForTypes:fileType]) {
  138.  
  139.       /* open all the files returned by the open panel */
  140.     files = [openPanel filenames];
  141.     for (files = [openPanel filenames]; files && *files; files++) {
  142.         strcpy(fullName, [openPanel directory]);
  143.         strcat(fullName, "/");
  144.         strcat(fullName, *files);
  145.         suffix = strrchr(*files, '.');
  146.         if (suffix)
  147.         [self app:NXApp openFile:fullName type:++suffix];
  148.     }
  149.     }
  150.     return self;
  151. }
  152.  
  153. /* action method, called when the user chooses "New 2D" in the menu */
  154. - new2D:sender {
  155.     [[GraphDoc allocFromZone:[self zone]] init];
  156.     return self;
  157. }
  158.  
  159. /* action method, called when the user chooses "New 3D" in the menu */
  160. - new3D:sender {
  161.     [[Graph3DDoc allocFromZone:[self zone]] init];
  162.     return self;
  163. }
  164.  
  165. /*
  166.  * Loads the info panel from its separate nib section.  We set the version
  167.  * number in the info panel on the fly, which keeps it up to date
  168.  * automatically.  The VERS_NUM variable is created in the vers.c file, which
  169.  * is created by the vers_string shell command as part of the build process.
  170.  */
  171. - showInfoPanel:sender {
  172.     if (!infoPanel) {
  173.     extern char VERS_NUM[];
  174.     [NXApp loadNibSection:"Info.nib" owner:self withNames:NO];
  175.     if (strlen(VERS_NUM) > 0) {
  176.         char versionBuffer[100];
  177.         sprintf (versionBuffer, [[self stringTable] valueForStringKey:"version"], VERS_NUM);
  178.         [versString setStringValue:versionBuffer];
  179.     } else {
  180.         [versString setStringValue:""];
  181.     }            
  182.     }
  183.     [infoPanel makeKeyAndOrderFront:self];
  184.     return self;
  185. }
  186.  
  187. /* Loads the help panel from its separate nib section. */
  188. - showHelpPanel:sender {
  189.     if (!helpPanel)
  190.     [NXApp loadNibSection:"Help.nib" owner:self withNames:NO];
  191.     [helpPanel makeKeyAndOrderFront:self];
  192.     return self;
  193. }
  194.  
  195. /* Loads the 3D panel from its separate nib section. */
  196. - showThreeDPanel:sender {
  197.     if (!threeDPanel) {
  198.     [NXApp loadNibSection:"ThreeDPanel.nib" owner:self withNames:NO];
  199.       /*
  200.        * USE THIS METHOD CAREFULLY.  It should only be used for panels that
  201.        * never or rarely need to become key.  Usually this is because they
  202.        * have no areas for typing (as in this case), or else the user very
  203.        * rarely types in them (e.g., the Font panel).
  204.        */
  205.     [threeDPanel setBecomeKeyOnlyIfNeeded:YES];
  206.     }
  207.     [threeDPanel orderFront:self];
  208.     return self;
  209. }
  210.  
  211. /* Returns the 3D Panel */
  212. - (ThreeDPanel *)threeDPanel {
  213.     return threeDPanel;
  214. }
  215.  
  216. /* Returns the string table */
  217. - (NXStringTable *)stringTable {
  218.     char path[MAXPATHLEN+1];
  219.  
  220.     if (!stringTable && [[NXBundle mainBundle] getPath:path forResource:"Graph" ofType:"strings"]) {
  221.     stringTable = [[NXStringTable allocFromZone:[self zone]] init];
  222.     [stringTable readFromFile:path];
  223.     }
  224.     return stringTable;
  225. }
  226.  
  227. /*
  228.  * Returns the window for a given filename, if open.  We go through the window
  229.  * list looking for an window with the given file open.  Since there are many
  230.  * more windows in the window list than our document windows (panels, NXImage
  231.  * caches, the app icon,...), we check the delegate to know if its a document
  232.  * window.  We use realpath() to make sure we aren't fooled by symbolic links
  233.  * that lead to a file already opened via a different path.
  234.  */ 
  235. static Window *findDocWindow(const char *name) {
  236.     int count;
  237.     id document;
  238.     Window *window;
  239.     List *windowList;
  240.     const char *realPath;
  241.     const char *otherRealPath;
  242.     char realPathBuf[MAXPATHLEN+1];
  243.  
  244.     windowList = [NXApp windowList];
  245.     count = [windowList count];
  246.     realPath = realpath(name, realPathBuf) ? realPathBuf : name;
  247.     while (count--) {
  248.     window = [windowList objectAt:count];
  249.     document = [window delegate];
  250.     if (document && ([document isKindOf:[GraphDoc class]]
  251.              || [document isKindOf:[Graph3DDoc class]])) {
  252.         otherRealPath = [document realFilename];
  253.         if (otherRealPath && !strcmp(otherRealPath, realPath))
  254.         return window;
  255.     }
  256.     }
  257.     return nil;
  258. }
  259.  
  260. @end
  261.