home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.0 / NeXTSTEP3.0.iso / NextDeveloper / Examples / AppKit / Yap / YapApp.m < prev    next >
Text File  |  1992-06-16  |  9KB  |  304 lines

  1. /*
  2.  *  YapApp.m
  3.  *  Author: Ali Ozer
  4.  *  Created: Mar 89 for 0.9
  5.  *  Modified: Jul & Aug 89 for 1.0
  6.  *  Modified: Aug 90 for 2.0
  7.  *  Modified: Apr & Jun 91 and Jun 92 for 3.0. Localized Jan 92.
  8.  *
  9.  *  YapApp is the application class used in Yap. It implements the
  10.  *  central functionality of coordinating the output and document
  11.  *  windows, opening documents, managing shared panels, etc...
  12.  *
  13.  *  You may freely copy, distribute and reuse the code in this example.
  14.  *  NeXT disclaims any warranty of any kind, expressed or implied,
  15.  *  as to its fitness for any particular use.
  16.  */
  17.  
  18. #import <appkit/appkit.h>
  19. #import <objc/NXBundle.h>
  20. #import <objc/zone.h>
  21. #import <sys/param.h>
  22. #import "YapApp.h"
  23. #import "YapDocument.h"
  24. #import "YapOutput.h"
  25.  
  26. #define CANTOPENFILE_STRING NXLocalString("Could not open file.", NULL, "The user-specified file could not be opened")
  27. #define OK_STRING NXLocalString("OK", NULL, "Default response in alert panel")
  28. #define UNSAVEDDOCS_STRING NXLocalString("You have unsaved documents.", NULL, "Message given to user when he tries to quit the application without saving all of his documents.")
  29. #define REVIEW_STRING NXLocalString("Review Unsaved", NULL, "Choice (on a button) given to user which allows him/her to review all unsaved documents if he/she quits the application without saving them all first.")
  30. #define QUITANYWAY_STRING NXLocalString("Quit Anyway", NULL, "Choice (on a button) given to user which allows him/her to quit the application even though there are unsaved documents.")
  31. #define QUIT_STRING NXLocalString("Quit", NULL, "The operation of exiting the application.")
  32. #define CANCEL_STRING NXLocalString ("Cancel", NULL, "Button choice allowing user to cancel quit")
  33.  
  34.  
  35. @implementation YapApp
  36.  
  37. - outputView   
  38. {
  39.     return outputView;
  40. }
  41.  
  42. - outputWindow
  43. {
  44.     return [outputView window];
  45. }
  46.  
  47. #define DEFAULTWIDTH 612
  48. #define DEFAULTHEIGHT 792
  49. #define MINSIZE 72
  50. #define MAXSIZE 3600
  51.  
  52. /*
  53.  * Here we have a handle to the output window, created in IB. We create
  54.  * the scroll and the yap output views and add them to this window.
  55.  */
  56. - setOutputWindow:anObject 
  57. {
  58.     NXRect initFrame = {{0.0, 0.0}, {DEFAULTWIDTH, DEFAULTHEIGHT}};
  59.  
  60.     id scrollView = [ScrollView new];
  61.  
  62.     outputView = [[YapOutput allocFromZone:[self zone]] initFrame:&initFrame];
  63.  
  64.     [a!0aect setBackgroundGray:NX_WHITE];
  65.     [anObject removeFromEventMask:NX_KEYDOWNMASK|NX_KEYUPMASK];
  66.     
  67.     [scrollView setBorderType:NX_NOBORDER];
  68.     [scrollView setHorizScrollerRequired:YES];
  69.     [scrollView setVertScrollerRequired:YES];
  70.  
  71.     [anObject setContentView:scrollView];
  72.     [scrollView setDocView:outputView];
  73.  
  74.     [anObject setDelegate:self]; // So we can get windowWillResize:toSize:
  75.     [anObject setFrameAutosaveName:"Output Window"];
  76.     [anObject makeKeyAndOrderFront:nil];
  77.  
  78.     [NXApp updateOutputWindowSize];
  79.  
  80.     return self;
  81. }
  82.  
  83. /*
  84.  * updateOutputWindowSize should be called after the size of the output view is
  85.  * changed. It simply makes sure the window isn't too big for the view. If the
  86.  * window is indeed to big, it is resized smaller.
  87.  */
  88. - updateOutputWindowSize
  89. {
  90.     NXRect frame, content;
  91.     NXSize maxWindowSize;
  92.  
  93.     // The next few lines allow us to get the window size for the window
  94.     // containing a ScrollView and the yap output view.
  95.  
  96.     [[self outputView] getFrame:&frame];
  97.     [ScrollView getFrameSize:&maxWindowSize forContentSize:&(frame.size)
  98.             horizScroller:YES vertScroller:YES borderType:NX_NOBORDER];
  99.  
  100.     // sizeWindow:: wants window size in content area; so we can use the
  101.     // maxWindowSize from above. But to compare it to the window frame,
  102.     // we first need to get the content area for the current frame.
  103.  
  104.     [[self outputWindow] getFrame:&frame];      
  105.     [Window getContentRect:&content forFrameRect:&frame 
  106.         style:[[self outputWindow] style]];
  107.  
  108.     if (content.size.width > maxWindowSize.width ||
  109.     content.size.height > maxWindowSize.height) { 
  110.     [[self outputWindow] 
  111.         sizeWindow:MIN(maxWindowSize.width, content.size.width)
  112.               :MIN(maxWindowSize.height, content.size.height)];
  113.     }
  114.  
  115.     // Now we go from the content size to the window frame size, which is 
  116.     // what we will use in windowWillResize:toSize:
  117.  
  118.     content.size = maxWindowSize;
  119.     [Window getFrameRect:&frame forContentRect:&content
  120.         style:[[self outputWindow] style]];
  121.  
  122.     maxWindowSize = frame.size;
  123.     [[self outputWindow] setMaxSize:&maxWindowSize];
  124.  
  125.     return self;
  126. }
  127.  
  128. /*
  129.  * newDocument simply creates a new Yap document and displays it.
  130.  */
  131. - newDocument:sender
  132. {
  133.     [YapDocument new];
  134.  
  135.     return self;
  136. }
  137.  
  138. /*
  139.  * openDocument gets a file name from the user, creates a new document !0bow,
  140.  * and loads the specified file into it.
  141.  */
  142. - openDocument:sender
  143. {
  144.     // Allow ps, eps, and any other extension not handled by other apps.
  145.     // Note that "" should come first in the list.
  146.     static const char *const yapTypes[] = {"", "ps", "eps", NULL};  
  147.  
  148.     if ([[OpenPanel new] runModalForTypes:yapTypes]) {
  149.     if ([YapDocument newFromFile:[[OpenPanel new] filename]] == nil) {
  150.         NXRunAlertPanel (NULL, CANTOPENFILE_STRING, OK_STRING, NULL, NULL);
  151.     }
  152.     }
  153.  
  154.     return self;
  155. }
  156.  
  157. /*
  158.  * app:openFile:type: is invoked by Workspace when the user double-clicks
  159.  * on a file Yap is prepared to accept. By default, Yap is not prepared to open
  160.  * any files, however, it can easily be made to open files of certain type
  161.  * through Project Builder.
  162.  */
  163. - (int)app:app openFile:(const char *)path type:(const char *)type
  164. {
  165.     if ([YapDocument newFromFile:path] == nil) return NO;
  166.     else return YES;
  167. }
  168.  
  169. /*
  170.  * The following method indicates that Yap is ready to open multiple
  171.  * files at one time.
  172.  */
  173. - (BOOL)appAcceptsAnotherFile:sender
  174. {
  175.     return YES;
  176. }
  177.  
  178. /*
  179.  * Methods to load .nib files for the various panels.
  180.  */
  181. - showInfo:sender
  182. {
  183.     if (!infoPanel) {
  184.         if (![NXApp loadNibSection:"Info.nib" owner:self withNames:NO fromZone:[self zone]]) {
  185.         NXLogError ("Can't find Info.nib!");    
  186.     }
  187.     }
  188.     [infoPanel makeKeyAndOrderFront:sender];
  189.     return self;
  190. }
  191.  
  192. - showHelp:sender
  193. {
  194.     if (!helpPanel) {
  195.         if (![NXApp loadNibSection:"Help.nib" owner:self withNames:NO fromZone:[self zone]]) {
  196.         NXLogError ("Can't find Help.nib!");    
  197.     }
  198.     }
  199.     [helpPanel makeKeyAndOrderFront:sender];
  200.     return self;
  201. }
  202.  
  203. - showPrefs:sender
  204. {
  205.     if (!prefsPanel) {
  206.         if (![NXApp loadNibSection:"Prefs.nib" owner:self withNames:NO fromZone:[self zone]]) {
  207.         NXLogError ("Can't find Prefs.nib!");    
  208.     }
  209.     [self updatePreferencesPanel:sender];
  210.     }
  211.     [prefsPanel makeKeyAndOrderFront:sender];
  212.     return self;
  213. }
  214.  
  215. /*
  216.  * updatePreferencesPanel: is used to copy the existing situation into
  217.  * the Prefences panel.
  218.  */
  219. - updatePreferencesPanel:sender
  220. {
  221.     NXRect outputFrame;
  222.  
  223.     [[self outputView] getFrame:&outputFrame];
  224.     [outputWidthField setFloatValue:NX_WIDTH(&outputFrame)];
  225.     [outputHeightField setFloatValue:NX_HEIGHT(&outputFrame)];
  226.     [showCacheButton setState:[[self outputView] isCacheShown]];
  227.     [clearCacheButto!0ctState:[[self outputView] isCacheCleared]];
  228.  
  229.     [outputWidthField selectText:sender];
  230.  
  231.     return self;
  232. }
  233.  
  234. /*
  235.  * okPreferencesPanel: causes the values in Preferences to be read into the
  236.  * application and applied to the various objects.
  237.  */
  238. - okPreferencesPanel:sender
  239. {
  240.     NXCoord desiredWidth, desiredHeight;
  241.  
  242.     desiredWidth = [outputWidthField floatValue];
  243.     if (desiredWidth < MINSIZE || desiredWidth > MAXSIZE) {
  244.     desiredWidth = MIN(MAX(desiredWidth, MINSIZE), MAXSIZE);
  245.     [outputWidthField setFloatValue:desiredWidth];
  246.     }
  247.     desiredHeight = [outputHeightField floatValue];
  248.     if (desiredHeight < MINSIZE || desiredHeight > MAXSIZE) {
  249.     desiredHeight = MIN(MAX(desiredHeight, MINSIZE), MAXSIZE);
  250.     [outputHeightField setFloatValue:desiredHeight];
  251.     }
  252.  
  253.     [[self outputView] sizeTo:desiredWidth :desiredHeight];
  254.     [self updateOutputWindowSize];
  255.  
  256.     [[self outputView] setCacheShown:[showCacheButton state]];
  257.     [[self outputView] setCacheCleared:[clearCacheButton state]];
  258.  
  259.     [[sender window] orderOut:sender];
  260.     [outputWidthField selectText:sender];
  261.  
  262.     return self;
  263. }
  264.  
  265. /*
  266.  * Make sure all documents are saved before actually terminating the app...
  267.  */
  268. - terminate:sender
  269. {
  270.     int count = [[self windowList] count];
  271.     BOOL needsSaving = NO;
  272.  
  273.     // Determine if there are any unsaved documents...
  274.  
  275.     while (!needsSaving && count--) {
  276.     id document = [YapDocument documentForWindow:[windowList objectAt:count]];
  277.     if (document && [document needsSaving]) {
  278.         needsSaving = YES;
  279.     }
  280.     }
  281.  
  282.     if (needsSaving) {
  283.     int choice = NXRunAlertPanel(QUIT_STRING, UNSAVEDDOCS_STRING, REVIEW_STRING, QUITANYWAY_STRING, CANCEL_STRING);
  284.     if (choice == NX_ALERTOTHER)  {
  285.         return self;                // Cancel
  286.     } else if (choice == NX_ALERTDEFAULT) {
  287.         count = [[self windowList] count];
  288.         while (count--) {
  289.         id document = [YapDocument documentForWindow:[windowList objectAt:count]];
  290.         if (document) {
  291.             if (![document closeDocument:QUIT_STRING andWindow:YES]) {
  292.             return self;            // Cancel
  293.             }            
  294.         }
  295.         }
  296.     }
  297.     }
  298.  
  299.     return [super terminate:sender];
  300. }
  301.  
  302. @end
  303.  
  304.