This is Controller.m in view mode; [Download] [Up]
// Controller.m // By Jayson Adams // NeXT Strategic Developer Engineer // // 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 <libc.h> // for strcmp(), index(), rindex() #import <streams/streams.h> #import <appkit/publicWraps.h> // for NXConvertWinNumToGlobal() #import <appkit/Control.h> #import <appkit/NXImage.h> #import <appkit/ScrollView.h> #import <appkit/Text.h> #import <appkit/Listener.h> #import <appkit/Speaker.h> #import <appkit/Window.h> #import <appkit/OpenPanel.h> #import <appkit/SavePanel.h> #import <appkit/Application.h> #import "CopyIcon.h" #import "FileImage.h" #import "GraphicImage.h" #import "Controller.h" @implementation Controller /* instance methods */ - appDidInit:sender { [Text registerDirective:"FileImage" forClass:[FileImage class]]; [Text registerDirective:"GraphicImage" forClass:[GraphicImage class]]; [self registerWindow]; [textObj setSel:0 :0]; return self; } - registerWindow { unsigned int windowNum; id speaker; /* register our app icon window with the workspace */ NXConvertWinNumToGlobal([[textObj window] windowNum], &windowNum); speaker = [NXApp appSpeaker]; [speaker setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)]; [speaker registerWindow:windowNum toPort:[[NXApp appListener] listenPort]]; return self; } static BOOL isEPSOrTIFF(char *filePath) { char *extension; if (!(extension = rindex(filePath, '.'))) { return NO; } return (!strcmp(".eps", extension) || !strcmp(".tiff", extension)); } - (int)iconEntered:(int)windowNum at:(double)x :(double)y iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY iconWidth:(double)iconWidth iconHeight:(double)iconHeight pathList:(char *)pathList { char *stringPosition; int files=1; id newImage, newGraphic; NXSize size = {48.0, 48.0}; struct stat statData; /* the number of tabs + 1 equals the number of files dragged in */ stringPosition = pathList; while (stringPosition = index(stringPosition, '\t')) { files++; stringPosition++; } /* make sure the user dragged one file in (and it wasn't root) */ if ((files > 1) || !(*pathList)) { acceptedIcon = NO; return 0; } /* punt if a directory */ stat(pathList, &statData); if (statData.st_mode & S_IFDIR) { acceptedIcon = NO; return 0; } acceptedIcon = YES; if (isEPSOrTIFF(pathList)) { /* copy the tiff or eps image into the text object */ newImage = [[NXImage alloc] initFromFile:pathList]; newGraphic = [[GraphicImage alloc] initForImage:newImage]; [textObj replaceSelWithCell:newGraphic]; } else { /* * use some PostScript code to copy the bits from the Workspace * window into our NXImage */ newImage = [[NXImage alloc] initSize:&size]; if ([newImage lockFocus]) { copyIconPicture(iconWindowNum, iconX, iconY, iconWidth, iconHeight); [newImage unlockFocus]; newGraphic = [[FileImage alloc] initForImage:newImage fileName:pathList]; [textObj replaceSelWithCell:newGraphic]; } } return 0; } - (int)iconExitedAt:(double)x :(double)y { NXSelPt start, end; if (acceptedIcon) { [[textObj getSel:&start :&end] setSel:start.cp - 1 :start.cp]; [textObj replaceSel:""]; } return 0; } - (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag { if (acceptedIcon) { *flag = 1; } else { *flag = 0; } return 0; } - lipService:sender { id uniqueLipImage, lips; /* * we could use findImageNamed: to get the image, but it always returns the * same instance for a given name. This causes problems when we have two * graphicImages using the lips icon 'cause when they get freed, they both * free the same nximage (and the app crashes). We can't do something like * [[NXImage findImageNamed:"lips"] copy] 'cause the copy method only * duplicates the nximage, not any of its representations. Using * initFromSection: is a reasonable workaround. */ uniqueLipImage = [[NXImage alloc] initFromSection:"lips.tiff"]; lips = [[GraphicImage alloc] initForImage:uniqueLipImage]; [textObj replaceSelWithCell:lips]; return self; } #define OPEN 1 #define OPEN_RTF_AS_ASCII 2 - open:sender { id openPanel; NXStream *stream; const char *types[2] = {"rtf", NULL}; openPanel = [OpenPanel new]; [openPanel allowMultipleFiles:NO]; if ([openPanel runModalForTypes:types]) { stream = NXMapFile([openPanel filename], NX_READONLY); if ([[sender selectedCell] tag] == OPEN_RTF_AS_ASCII) { [textObj readText:stream]; } else { [textObj readRichText:stream]; } NXCloseMemory(stream, NX_FREEBUFFER); [textObj setSel:0 :0]; } return self; } - save:sender { id savePanel; NXStream *stream; savePanel = [SavePanel new]; [savePanel setRequiredFileType:"rtf"]; if ([savePanel runModal]) { stream = NXOpenMemory(NULL, 0, NX_WRITEONLY); [textObj writeRichText:stream]; if (NXSaveToFile(stream, [savePanel filename]) == -1) { NXRunAlertPanel(NULL, "Couldn't write file", NULL, NULL, NULL); } NXCloseMemory(stream, NX_FREEBUFFER); } return self; } - windowWillResize:sender toSize:(NXSize *)frameSize { if (frameSize->height < 200.0) { frameSize->height = 200.0; } if (frameSize->width < 200.0) { frameSize->width = 200.0; } return self; } - info:sender { if (!infoPanel) { [NXApp loadNibSection:"Info.nib" owner:self]; } [infoPanel makeKeyAndOrderFront:NULL]; return self; } /* outlet initialization */ - setScrollView:anObject { scrollView = anObject; textObj = [scrollView docView]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.