Annotation of Examples/AppKit/Yap/YapApp.m, revision 1.1.1.1

1.1       root        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:     [anObject 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 window,
                    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:     [clearCacheButton setState:[[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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.