home *** CD-ROM | disk | FTP | other *** search
- // 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