Annotation of Examples/AppKit/Yap/YapApp.m, revision 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.