This is YapApp.m in view mode; [Download] [Up]
/* * YapApp.m * Author: Ali Ozer * Created: Mar 89 for 0.9 * Modified: Jul & Aug 89 for 1.0 * Modified: Aug 90 for 2.0 * Modified: Apr & Jun 91 and Jun 92 for 3.0. Localized Jan 92. * * YapApp is the application class used in Yap. It implements the * central functionality of coordinating the output and document * windows, opening documents, managing shared panels, etc... * * You may freely copy, distribute and reuse the code in this example. * NeXT disclaims any warranty of any kind, expressed or implied, * as to its fitness for any particular use. */ #import <appkit/appkit.h> #import <objc/NXBundle.h> #import <objc/zone.h> #import <sys/param.h> #import "YapApp.h" #import "YapDocument.h" #import "YapOutput.h" #define CANTOPENFILE_STRING NXLocalString("Could not open file.", NULL, "The user-specified file could not be opened") #define OK_STRING NXLocalString("OK", NULL, "Default response in alert panel") #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.") #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.") #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.") #define QUIT_STRING NXLocalString("Quit", NULL, "The operation of exiting the application.") #define CANCEL_STRING NXLocalString ("Cancel", NULL, "Button choice allowing user to cancel quit") @implementation YapApp - outputView { return outputView; } - outputWindow { return [outputView window]; } #define DEFAULTWIDTH 612 #define DEFAULTHEIGHT 792 #define MINSIZE 72 #define MAXSIZE 3600 /* * Here we have a handle to the output window, created in IB. We create * the scroll and the yap output views and add them to this window. */ - setOutputWindow:anObject { NXRect initFrame = {{0.0, 0.0}, {DEFAULTWIDTH, DEFAULTHEIGHT}}; id scrollView = [ScrollView new]; outputView = [[YapOutput allocFromZone:[self zone]] initFrame:&initFrame]; [anObject setBackgroundGray:NX_WHITE]; [anObject removeFromEventMask:NX_KEYDOWNMASK|NX_KEYUPMASK]; [scrollView setBorderType:NX_NOBORDER]; [scrollView setHorizScrollerRequired:YES]; [scrollView setVertScrollerRequired:YES]; [anObject setContentView:scrollView]; [scrollView setDocView:outputView]; [anObject setDelegate:self]; // So we can get windowWillResize:toSize: [anObject setFrameAutosaveName:"Output Window"]; [anObject makeKeyAndOrderFront:nil]; [NXApp updateOutputWindowSize]; return self; } /* * updateOutputWindowSize should be called after the size of the output view is * changed. It simply makes sure the window isn't too big for the view. If the * window is indeed to big, it is resized smaller. */ - updateOutputWindowSize { NXRect frame, content; NXSize maxWindowSize; // The next few lines allow us to get the window size for the window // containing a ScrollView and the yap output view. [[self outputView] getFrame:&frame]; [ScrollView getFrameSize:&maxWindowSize forContentSize:&(frame.size) horizScroller:YES vertScroller:YES borderType:NX_NOBORDER]; // sizeWindow:: wants window size in content area; so we can use the // maxWindowSize from above. But to compare it to the window frame, // we first need to get the content area for the current frame. [[self outputWindow] getFrame:&frame]; [Window getContentRect:&content forFrameRect:&frame style:[[self outputWindow] style]]; if (content.size.width > maxWindowSize.width || content.size.height > maxWindowSize.height) { [[self outputWindow] sizeWindow:MIN(maxWindowSize.width, content.size.width) :MIN(maxWindowSize.height, content.size.height)]; } // Now we go from the content size to the window frame size, which is // what we will use in windowWillResize:toSize: content.size = maxWindowSize; [Window getFrameRect:&frame forContentRect:&content style:[[self outputWindow] style]]; maxWindowSize = frame.size; [[self outputWindow] setMaxSize:&maxWindowSize]; return self; } /* * newDocument simply creates a new Yap document and displays it. */ - newDocument:sender { [YapDocument new]; return self; } /* * openDocument gets a file name from the user, creates a new document window, * and loads the specified file into it. */ - openDocument:sender { // Allow ps, eps, and any other extension not handled by other apps. // Note that "" should come first in the list. static const char *const yapTypes[] = {"", "ps", "eps", NULL}; if ([[OpenPanel new] runModalForTypes:yapTypes]) { if ([YapDocument newFromFile:[[OpenPanel new] filename]] == nil) { NXRunAlertPanel (NULL, CANTOPENFILE_STRING, OK_STRING, NULL, NULL); } } return self; } /* * app:openFile:type: is invoked by Workspace when the user double-clicks * on a file Yap is prepared to accept. By default, Yap is not prepared to open * any files, however, it can easily be made to open files of certain type * through Project Builder. */ - (int)app:app openFile:(const char *)path type:(const char *)type { if ([YapDocument newFromFile:path] == nil) return NO; else return YES; } /* * The following method indicates that Yap is ready to open multiple * files at one time. */ - (BOOL)appAcceptsAnotherFile:sender { return YES; } /* * Methods to load .nib files for the various panels. */ - showInfo:sender { if (!infoPanel) { if (![NXApp loadNibSection:"Info.nib" owner:self withNames:NO fromZone:[self zone]]) { NXLogError ("Can't find Info.nib!"); } } [infoPanel makeKeyAndOrderFront:sender]; return self; } - showHelp:sender { if (!helpPanel) { if (![NXApp loadNibSection:"Help.nib" owner:self withNames:NO fromZone:[self zone]]) { NXLogError ("Can't find Help.nib!"); } } [helpPanel makeKeyAndOrderFront:sender]; return self; } - showPrefs:sender { if (!prefsPanel) { if (![NXApp loadNibSection:"Prefs.nib" owner:self withNames:NO fromZone:[self zone]]) { NXLogError ("Can't find Prefs.nib!"); } [self updatePreferencesPanel:sender]; } [prefsPanel makeKeyAndOrderFront:sender]; return self; } /* * updatePreferencesPanel: is used to copy the existing situation into * the Prefences panel. */ - updatePreferencesPanel:sender { NXRect outputFrame; [[self outputView] getFrame:&outputFrame]; [outputWidthField setFloatValue:NX_WIDTH(&outputFrame)]; [outputHeightField setFloatValue:NX_HEIGHT(&outputFrame)]; [showCacheButton setState:[[self outputView] isCacheShown]]; [clearCacheButton setState:[[self outputView] isCacheCleared]]; [outputWidthField selectText:sender]; return self; } /* * okPreferencesPanel: causes the values in Preferences to be read into the * application and applied to the various objects. */ - okPreferencesPanel:sender { NXCoord desiredWidth, desiredHeight; desiredWidth = [outputWidthField floatValue]; if (desiredWidth < MINSIZE || desiredWidth > MAXSIZE) { desiredWidth = MIN(MAX(desiredWidth, MINSIZE), MAXSIZE); [outputWidthField setFloatValue:desiredWidth]; } desiredHeight = [outputHeightField floatValue]; if (desiredHeight < MINSIZE || desiredHeight > MAXSIZE) { desiredHeight = MIN(MAX(desiredHeight, MINSIZE), MAXSIZE); [outputHeightField setFloatValue:desiredHeight]; } [[self outputView] sizeTo:desiredWidth :desiredHeight]; [self updateOutputWindowSize]; [[self outputView] setCacheShown:[showCacheButton state]]; [[self outputView] setCacheCleared:[clearCacheButton state]]; [[sender window] orderOut:sender]; [outputWidthField selectText:sender]; return self; } /* * Make sure all documents are saved before actually terminating the app... */ - terminate:sender { int count = [[self windowList] count]; BOOL needsSaving = NO; // Determine if there are any unsaved documents... while (!needsSaving && count--) { id document = [YapDocument documentForWindow:[windowList objectAt:count]]; if (document && [document needsSaving]) { needsSaving = YES; } } if (needsSaving) { int choice = NXRunAlertPanel(QUIT_STRING, UNSAVEDDOCS_STRING, REVIEW_STRING, QUITANYWAY_STRING, CANCEL_STRING); if (choice == NX_ALERTOTHER) { return self; // Cancel } else if (choice == NX_ALERTDEFAULT) { count = [[self windowList] count]; while (count--) { id document = [YapDocument documentForWindow:[windowList objectAt:count]]; if (document) { if (![document closeDocument:QUIT_STRING andWindow:YES]) { return self; // Cancel } } } } } return [super terminate:sender]; } - yapSelection:pasteboard userData:(const char *)userData error:(char **)msg { const NXAtom *types; char *posting; int postingLength; char buf[MAXPATHLEN+1]; NXStream *ts; id filterboard; /* get the message */ filterboard = [Pasteboard newByFilteringTypesInPasteboard:pasteboard]; [filterboard types]; if ([filterboard readType:NXAsciiPboardType data:&posting length:&postingLength]) { ts = NXOpenMemory(NULL, 0, NX_READWRITE); NXWrite(ts, posting, postingLength); NXSeek(ts,0,NX_FROMSTART); [YapDocument newFromStream:ts name:NULL]; //NXCloseMemory(ts, NX_FREEBUFFER); [filterboard deallocatePasteboardData:posting length:postingLength]; } else {*msg = "Could not read selection"; return nil;} [filterboard free]; return self; }; - appDidInit:sender { [[NXApp appListener] setServicesDelegate:self]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.