This is SketchView.m in view mode; [Download] [Up]
/*****************************************************************************/ /* SketchView.m */ /* implementation file for SketchView class of the SketchDemo application */ /* August 1989 Carl F. Sutter */ /*****************************************************************************/ #import "SketchView.h" #import <appkit/appkit.h> @implementation SketchView /*****************************************************************************/ /* newFrame - create an instance of SketchView, and initialize it */ /*****************************************************************************/ + newFrame:(NXRect *)rect { int i; NXPoint nxpHotSpot; /* make a new view, and initialize some flags */ self = [super newFrame:rect]; nTool = TOOL_RECT; bOpenedWithFile = FALSE; nCurPage = 1; /* make the open and save-as panels */ openReq = [OpenPanel new]; saveReq = [SavePanel new]; [saveReq setRequiredFileType:"sketchD"]; /* create the bitmaps */ for (i=0; i<MAXPAGES; i++) { bmpPage[i] = [Bitmap newSize:bounds.size.width :bounds.size.height type:NX_ALPHABITMAP]; [bmpPage[i] setFlip:NO]; } /* get the drawing cursor and set it's hot spot */ curDraw = [Cursor newFromMachO:"DrawCursor.tiff"]; nxpHotSpot.x = 7.0; nxpHotSpot.y = 7.0; [curDraw setHotSpot:&nxpHotSpot]; return( self ); } /* newFrame 8/16/89 CFS */ /*****************************************************************************/ /* outlet initialization methods */ /*****************************************************************************/ - setNewAlpha:anObject { newAlpha = anObject; return( self ); } - setPageNum:anObject { pageNum = anObject; return( self ); } - setNumToDraw:anObject { numToDraw = anObject; return( self ); } /*****************************************************************************/ /* appDidInit - delegate message sent after application is set up */ /* this is the time for setting fields etc. */ /*****************************************************************************/ - appDidInit:(id)sender { /* clear the pages, unless a file was just loaded in to start the App */ if (!bOpenedWithFile) [self clearPages:self]; return( self ); } /* appDidInit 8/16/89 CFS */ /*****************************************************************************/ /* appAcceptsAnotherFile is an application delegate method which */ /* returns whether it is OK for the application to try to open more files */ /* with the appOpenFile:type: */ /*****************************************************************************/ - (BOOL)appAcceptsAnotherFile:sender; { return( YES ); } /* appAcceptsAnotherFile 11/2/89 CFS */ /*****************************************************************************/ /* appOpenFile:type: - delegate message sent to open the specified file. */ /* It is normally called by the Application object in response to open */ /* requests from the Workspace. */ /*****************************************************************************/ - (int)appOpenFile:(const char *)filename type:(const char *)aType; { /* set the app icon as the Miniwindow icon */ [window setMiniwindowIcon:"app"]; /* bOpenedWithFile only used for initialization, since if the user double */ /* clicks a file in the workspace to start the App, appOpenFile arrives */ /* BEFORE appDidInit! (due to Listener weirdness) */ bOpenedWithFile = TRUE; return( [self openSketchPad:filename] ); } /* appOpenFile 9/11/89 CFS */ /*****************************************************************************/ /* newPage - flip to the page entered by the user */ /*****************************************************************************/ - newPage:sender { nCurPage = MAX( 1, MIN( MAXPAGES, [pageNum intValueAt:0] ) ); [pageNum setIntValue:nCurPage at:0]; [pageNum selectTextAt:0]; [self display]; return( self ); } /* newPage 8/16/89 CFS */ /*****************************************************************************/ /* clearPages - erase all the pages, and reset tablet */ /*****************************************************************************/ - clearPages:sender { float flNewAlpha; int i; strcpy( szFileName, UNTITLED ); [self setTitle]; /* get the new alpha value */ [newAlpha selectTextAt:0]; flNewAlpha = [newAlpha floatValueAt:0]; /* white out the pages */ for (i=0; i<MAXPAGES; i++) { [bmpPage[i] lockFocus]; PSsetalpha( flNewAlpha ); PSsetgray( NX_WHITE ); NXRectFill( &bounds ); [bmpPage[i] unlockFocus]; } /* set the new page number, and redraw the sheets */ nCurPage = 1; [pageNum setIntValue:nCurPage at:0]; [self display]; return( self ); } /* clearPages 8/16/89 CFS */ /*****************************************************************************/ /* setTool - set the current drawing tool */ /*****************************************************************************/ - setTool:sender { nTool = [[sender selectedCell] tag]; return( self ); } /* setTool 8/16/89 CFS */ /*****************************************************************************/ /* flipUp - flip up one page */ /*****************************************************************************/ - flipUp:sender { if (nCurPage > 1) nCurPage--; [pageNum setIntValue:nCurPage at:0]; [self display]; return( self ); } /* flipUp 8/16/89 CFS */ /*****************************************************************************/ /* flipDown - flip down one page */ /*****************************************************************************/ - flipDown:sender { if (nCurPage < MAXPAGES) nCurPage++; [pageNum setIntValue:nCurPage at:0]; [self display]; return( self ); } /* flipDown 8/16/89 CFS */ /*****************************************************************************/ /* drawSelf - draw the pages in order up to the current page */ /*****************************************************************************/ - drawSelf:(NXRect *)r :(int) count { int i; int nStartPage; nStartPage = MAX( 0, nCurPage - [numToDraw intValue] ); PSsetgray( NX_WHITE ); NXRectFill( &bounds ); for (i=nStartPage; i<nCurPage; i++) [bmpPage[i] composite:NX_SOVER toPoint:&bounds.origin]; return( self ); } /* drawSelf 8/16/89 CFS */ /*****************************************************************************/ /* animate - draw the frames back in sequence */ /*****************************************************************************/ - animate:sender; { int i; [self lockFocus]; PSsetgray( NX_WHITE ); NXRectFill( &bounds ); for (i=0; i<nCurPage; i++) { [bmpPage[i] composite:NX_COPY toPoint:&bounds.origin]; [[self window] flushWindow]; } [self unlockFocus]; [self display]; return( self ); } /* animate 8/16/89 CFS */ /*****************************************************************************/ /* mouseDown - trap mouse movements, and draw new graphics */ /* the drawing is very crude here, no pswraps or anything */ /*****************************************************************************/ - mouseDown:(NXEvent *)e { BOOL bLooping = YES; int nOldMask; NXPoint pA, pB; /* use standard instance drawing to rubber-band or draw a graphic */ nOldMask = [window addToEventMask:NX_MOUSEDRAGGEDMASK]; pA = e->location; [self convertPoint:&pA fromView:nil]; [self lockFocus]; while (bLooping) { e = [NXApp getNextEvent:NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK]; pB = e->location; [self convertPoint:&pB fromView:nil]; PSnewinstance(); if (bLooping = (e->type == NX_MOUSEDRAGGED)) switch (nTool) { case TOOL_RECT: /* rubber band a rectangle */ PSsetinstance( YES ); PSsetgray( NX_BLACK ); PSrectstroke( pA.x, pA.y, pB.x - pA.x, pB.y - pA.y ); PSsetinstance( NO ); break; case TOOL_LINE: /* rubber band a line */ PSsetinstance( YES ); PSsetgray( NX_BLACK ); PSmoveto( pA.x, pA.y ); PSlineto( pB.x, pB.y ); PSstroke(); PSsetinstance( NO ); break; case TOOL_PENCIL: /* draw a line right on the current bitmap */ PSsetgray( NX_BLACK ); PSmoveto( pA.x, pA.y ); PSlineto( pB.x, pB.y ); PSstroke(); [window flushWindow]; [bmpPage[nCurPage - 1] lockFocus]; PSsetgray( NX_BLACK ); PSmoveto( pA.x, pA.y ); PSlineto( pB.x, pB.y ); PSstroke(); [bmpPage[nCurPage - 1] unlockFocus]; pA = pB; break; } /* nTool switch */ } [self unlockFocus]; [window setEventMask:nOldMask]; /* draw the rubber banded rectangle or line on the current bitmap */ [bmpPage[nCurPage - 1] lockFocus]; PSsetgray( NX_BLACK ); if (nTool == TOOL_RECT) PSrectstroke( pA.x, pA.y, pB.x - pA.x, pB.y - pA.y ); if (nTool == TOOL_LINE) { PSmoveto( pA.x, pA.y ); PSlineto( pB.x, pB.y ); PSstroke(); } [bmpPage[nCurPage - 1] unlockFocus]; [self display]; return( self ); } /* mouseDown 8/12/89 CFS */ /*****************************************************************************/ /* showError - display an error message in an alert panel */ /*****************************************************************************/ - showError:(char *)errorMessage { NXRunAlertPanel( "SketchDemo Error", errorMessage, "OK", NULL, NULL ); } /* showError 9/11/89 CFS */ /*****************************************************************************/ /* openRequest - opens a new file using the open panel */ /*****************************************************************************/ - openRequest:sender { const char *fileName; const char *const types[2] = {"sketchD", NULL}; if ([openReq runModalForTypes:types] && (fileName = [openReq filename])) [self openSketchPad:fileName]; return( self ); } /* openRequest 9/11/89 CFS */ /*****************************************************************************/ /* openSketchPad - read the file and load the bitmaps */ /*****************************************************************************/ - (BOOL)openSketchPad:(const char *)fileName { NXTypedStream *ts; int i; if (!(ts = NXOpenTypedStreamForFile( fileName, NX_READONLY ))) { [self showError:"Couldn't open file."]; return( NO ); } /* file opened OK, load in the bitmaps and set the new filename */ [NXWait push]; for (i=0; i<MAXPAGES; i++) { /*[bmpPage[i] free];*/ /*bmpPage[i] = [Bitmap newFromStream:ts];*/ bmpPage[i] = NXReadObject( ts ); } NXCloseTypedStream( ts ); strcpy( szFileName, fileName ); [self setTitle]; [self display]; [NXWait pop]; return( YES ); } /* openSketchPad 9/11/89 CFS */ /*****************************************************************************/ /* saveRequest - saves the current window under its default name */ /* if the current szFileName is "Untitled" then use saveAsRequest */ /*****************************************************************************/ - saveRequest:sender { if (strcmp( szFileName, UNTITLED )) [self saveSketchPad:szFileName]; else [self saveAsRequest:sender]; return( self ); } /* saveRequest 9/11/89 CFS */ /*****************************************************************************/ /* saveAsRequest - gives the user a chance to save under a new name. */ /*****************************************************************************/ - saveAsRequest:sender { const char *fileName; char *name; char path[120]; /* split the filename into path and name */ strcpy( path, szFileName ); name = strrchr( path, '/' ); if (name) *name++ = '\0'; else { strcpy( path, "." ); name = szFileName; } /* bring up the save panel */ if (([saveReq runModalForDirectory:path file:name]) && (fileName = [saveReq filename])) [self saveSketchPad:fileName]; return( self ); } /* saveAsRequest 9/11/89 CFS */ /*****************************************************************************/ /* saveSketchPad - save the current bitmaps in the named file */ /*****************************************************************************/ - (BOOL)saveSketchPad:(const char *)fileName { NXTypedStream *ts; int i; if (!(ts = NXOpenTypedStreamForFile( fileName, NX_WRITEONLY ))) { [self showError:"Couldn't open file."]; return( NO ); } /* file opened OK, save the bitmaps */ [NXWait push]; for (i=0; i<MAXPAGES; i++) NXWriteObject( ts, bmpPage[i] ); NXCloseTypedStream( ts ); strcpy( szFileName, fileName ); [self setTitle]; [NXWait pop]; return( YES ); } /* saveSketchPad 9/11/89 CFS */ /*****************************************************************************/ /* resetCursorRects - override the View's method to add our drawing cursor */ /*****************************************************************************/ - resetCursorRects { [self addCursorRect:&bounds cursor:curDraw]; return( self ); } /* resetCursorRects 11/2/89 CFS */ /*****************************************************************************/ /* setTitle - set the window's title with the current file name */ /* don't be confused by the name of this method - a Window has a setTitle */ /* method, while a View (this code) does NOT. This is just an internal one. */ /*****************************************************************************/ - setTitle { const char *first; char szTitle[80]; /* get rid of any path info, if there is any */ first = strrchr( szFileName, '/' ); if (first == NULL) first = szFileName; else first++; /* character after last forward slash */ sprintf( szTitle, "Animation Sketch Pad - %s", first ); [window setTitle:szTitle]; } /* setTitle 11/9/89 CFS */ @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.