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. * For BBFig to deo BoundingBox computation.... * Modified: Jan 92 for BBFig by Izumi Ohzawa (izumi@pinoko.berkeley.edu) * Added Preferences: 92-05-14 Izumi Ohzawa. * * YapApp is the application class used in Yap. It implements the * central functionality of coordinating the output and document * windows, opening documents, 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 "YapApp.h" #import "YapDocument.h" #import "YapOutput.h" #import <stdio.h> #import <objc/List.h> #import <sys/param.h> @implementation YapApp - appDidInit:sender { float r, g, b; const char *sptr; static NXDefaultsVector BBFigDefaults = { {"BBoxMargin", "2"}, {"RubberBandColor", "1 0 0"}, {NULL} }; NXRegisterDefaults([NXApp appName], BBFigDefaults); bbmargin = atoi(NXGetDefaultValue([NXApp appName], "BBoxMargin")); if(bbmargin < 0) bbmargin = 0; if(bbmargin >20) bbmargin = 20; sptr = NXGetDefaultValue([NXApp appName], "RubberBandColor"); sscanf(sptr,"%f %f %f", &r, &g, &b); rbColor = NXConvertRGBToColor(r, g, b); // Store in globals without alpha [outputView setRubberBandColor:rbColor]; return self; } - 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 display]; [NXApp updateOutputWindowSize]; return self; } /* * windowWillResize:toSize: is a delegate method that gets called * when a window is being resized. In our case, we want to limit the user * from growing the output window to a size that is greater than that of the * view. */ - windowWillResize:sender toSize:(NXSize *)sz { if (sz->width > maxWindowSize.width) sz->width = maxWindowSize.width; if (sz->height > maxWindowSize.height) sz->height = maxWindowSize.height; 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; // 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; 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, "Could not open file.", "OK", NULL, NULL); } } return self; } /* * appOpenFile: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 the IB project inspector. */ - (int)appOpenFile:(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) { [self loadNibSection:"Info.nib" owner:self withNames:NO]; } [infoPanel makeKeyAndOrderFront:sender]; return self; } - showHelp:sender { if (!helpPanel) { [self loadNibSection:"Help.nib" owner:self withNames:NO]; } [helpPanel makeKeyAndOrderFront:sender]; return self; } - showPrefs:sender { if (!prefsPanel) { [self loadNibSection:"Prefs.nib" owner:self withNames:NO]; [self updatePreferencesPanel:sender]; } [prefsPanel makeKeyAndOrderFront:sender]; return self; } - bbmarginSliderAction:sender { /* just reflect the slider value into field */ [marginBBoxField setIntValue:[sender intValue]]; return self; } - (int)bbMargin { return bbmargin; } /* * 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]]; [showGridButton setState:[[self outputView] isMeshON]]; [computeBBoxButton setState:[[self outputView] isFigureBB]]; [marginBBoxSlider setIntValue:bbmargin]; [marginBBoxField setIntValue:bbmargin]; [outputWidthField selectText:sender]; [rbColorWell setColor:rbColor]; return self; } /* * okPreferencesPanel: causes the values in Preferences to be read into the * application and applied to the various objects. */ - okPreferencesPanel:sender { float red, green, blue, alpha; char strbuf[80]; 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]]; [[self outputView] setMeshON:[showGridButton state]]; [[self outputView] setFigureBB:[computeBBoxButton state]]; bbmargin = [marginBBoxSlider intValue]; [marginBBoxField setIntValue:bbmargin]; sprintf(strbuf, "%d", bbmargin); NXWriteDefault ([NXApp appName], "BBoxMargin", strbuf); rbColor = [rbColorWell color]; // get RGB components for storing in defaults NXConvertColorToRGBA(rbColor, &red, &green, &blue, &alpha); sprintf(strbuf, "%7.5f %7.5f %7.5f", red, green, blue); NXWriteDefault([NXApp appName], "RubberBandColor", strbuf); [outputView setRubberBandColor:rbColor]; [[sender window] orderOut:sender]; [outputWidthField selectText:sender]; return self; } /* This method code taken from Draw.app source */ - terminate:sender /* * Overridden to be sure all documents get an opportunity to be saved * before exiting the program. */ { int count, choice; id window, document; count = [windowList count]; /* windowList is in NXApp which this one is */ while (count--) { window = [windowList objectAt:count]; document = [window delegate]; if ([window isDocEdited]) { choice = NXRunAlertPanel("Quit", "You have unsaved documents.", "Review Unsaved", "Quit Anyway", "Cancel"); if (choice == NX_ALERTOTHER) { return self; } else if (choice == NX_ALERTDEFAULT) { count = [windowList count]; while (count--) { window = [windowList objectAt:count]; document = [window delegate]; if ([document respondsTo:@selector(windowWillClose:action:)]) { if ([document windowWillClose:window action:"Quit"]) { [window close]; } else { return self; } } } } break; } } [super terminate:sender]; return nil; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.