This is DrawView.m in view mode; [Download] [Up]
/* This class was created to control the drawing from within logo for the NeXT. Created by : Gary F. Desrochers (garyd@slate.mines.colorado.edu) Sean Kerstiens (skerstie@slate.mines.colorado.edu) Created For: Colorado School of Mines. Last edited: June 25,1992 */ #import "DrawView.h" #import <zone.h> #import <appkit/Matrix.h> #import <dpsclient/wraps.h> #import <appkit/NXImage.h> #import <appkit/NXEPSImageRep.h> #import <appkit/Control.h> #import <appkit/OpenPanel.h> #import <appkit/color.h> #import "pslogo.h" #import <stdlib.h> #import <mach.h> #import <appkit/Application.h> #import <appkit/OpenPanel.h> #import <appkit/SavePanel.h> @interface DrawView(DrawViewPrivate) // Declare methods static to this class. - _write:(const char *)filename; - _open:sender _newDrawing:(BOOL)doClear; - _read:(const char *)filename _newDrawing:(BOOL)doClear; - _doSaveWithNewName:(BOOL)doNewName retainName:(BOOL)doRetain; - _drawTurtleImage; @end @implementation DrawView - drawTurtleWith:(double)angle :(double)tox :(double)toy :(int)hide // This routine draws the Turtle when asked to by setting the boolean to YES, // setting the coordinates and then asking for a display. // should be combined with clearTurtle later. { // First check on whether to display the turtle or not. if(hide == 0) { //recache in a sense clears the NXImage. [idTurtle recache]; drawTurtle = YES; } else { drawTurtle = NO; } // Set angle and Coordinates. turtleAngle = -angle; sRect.origin.x = tox -22.7; sRect.origin.y = toy -32.5; return [self display]; } - initFrame:(const NXRect *)tF { [super initFrame:tF]; // Setup permanent for use later. // See the .h file for explanation of permanent variables. sRect.origin.x = bounds.size.width/2.0-22.7; sRect.origin.y = bounds.size.height/2.0-32.5; sRect.size.width = 45.4; sRect.size.height = 65.0; rRect = bounds; bbox[0] = rRect.origin.x; bbox[1] = rRect.origin.y; bbox[2] = rRect.size.width; bbox[3] = rRect.size.height; thisStruct = &firstStruct; thisStruct->nextStruct = NULL; drawTurtle = YES; // Make the Background a NXImage. Makes it so that for alot of the // things that need to be done (like clearing the turtle and showing the // turtle) easier. [(idBackground = [[NXImage allocFromZone:[self zone]] initSize:&rRect.size]) useDrawMethod:@selector(drawBack:) inObject:self]; // Now the turtle will be easier as a NXImage also. turtleAngle = 0.0; idTurtle=[[NXImage allocFromZone:[self zone]] initSize:&sRect.size]; // So that they are easier to Composite, set each background to clear. [idBackground setBackgroundColor:NX_COLORWHITE]; [idTurtle setBackgroundColor:NX_COLORCLEAR]; // We want the Turtle scalable. Just makes it easier to draw. [idTurtle setScalable:YES]; return self; } -drawSelf:(NXRect *)r: (int)count { // Always composite copy the background. [idBackground composite:NX_COPY toPoint:&rRect.origin]; // Draw the turtle only if drawTurtle is set to YES. if (drawTurtle) { [self _drawTurtleImage]; [idTurtle composite:NX_SOVER toPoint:&sRect.origin]; } return self; } - drawLine:(double)type :(double)fromx :(double)fromy :(double)tox: (double)toy; { // Lock the focus for our drawing of the line. [idBackground lockFocus]; // Make sure the Color is set to black. NXSetColor(NX_COLORBLACK); // Drawing the line is easy. Mix the Postscript commands into one command. PSWline (fromx,fromy,tox,toy); NXSetColor(NX_COLORWHITE); // Now unlock our focus. [idBackground unlockFocus]; // Now for the hard part. What if our drawing needs to be created from // scratch. This needs to be done when printing for instance. // Save the data for the lines into a linked list. // Later on the option may be added to remove the previous line drawn. // Wouldn't be to hard to do. // Fill up the two arrays. thisStruct->cArray[0] = dps_ucache; thisStruct->cArray[1] = dps_setbbox; thisStruct->oArray[0] = (float)fromx; thisStruct->oArray[1] = (float)fromy; thisStruct->cArray[2] = dps_moveto; thisStruct->oArray[2] = (float)tox; thisStruct->oArray[3] = (float)toy; thisStruct->cArray[3] = dps_lineto; thisStruct->nextStruct = (struct prStruct *)malloc(sizeof(struct prStruct)); thisStruct = thisStruct->nextStruct; thisStruct->nextStruct = NULL; // O.K. Everything set up for later. return [self display]; } -clearScreen; // A clear screen needs to remove everything in the link list except the // first element and then redraw the background. { struct prStruct *oldStruct = &firstStruct,*tempStruct = &firstStruct; // Free our old background. [idBackground free]; // Loop through the link lists and delete all the old lines. tempStruct = tempStruct->nextStruct; while(tempStruct != NULL) { oldStruct = tempStruct; tempStruct = tempStruct->nextStruct; free(oldStruct); } thisStruct = &firstStruct; thisStruct->nextStruct = NULL; // Now set get a new Background. [(idBackground = [[NXImage allocFromZone:[self zone]] initSize:&rRect.size]) useDrawMethod:@selector(drawBack:) inObject:self]; // Set background Attribute [idBackground setBackgroundColor:NX_COLORCLEAR]; return [self display]; } - drawBack: image // This routine will redraw the background if needed. It is called for // routines like the printing routine. { struct prStruct *tempStruct = &firstStruct; // Here is the big secret as how to get it to draw alot of lines real fast. // I guess you could also loop through the link list and calculate all the // values needed for one DPSDoUserPath. Never tried it. // Another way would be to make a typed memory stream. That way the linked // list could be gotten rid of. (Who knows? The Shadow knows!) while(tempStruct->nextStruct != NULL) { DPSDoUserPath(tempStruct->oArray,4,dps_float,tempStruct->cArray, 4,bbox,dps_ustroke); tempStruct = tempStruct->nextStruct; } return self; } - _drawTurtleImage // This routine calls the post script to draw the turtle image. { [idTurtle lockFocus]; PSWTurtle(turtleAngle); [idTurtle unlockFocus]; return self; } - print; { // Printing is rather simple; just send printPSCode: to the text view // you wish to print. The print panel will automatically pop up and unless // the user cancels the printout the text view will be printed. // This routine prints out the screen minus the turtle in postscript. // Need to save the old turtle type. BOOL save = drawTurtle; // First turn of compositing the turtle. drawTurtle = NO; // Find out stuff about printing. [NXApp printInfo]; // Print it out. It is that simple. [self printPSCode:self]; // Put the turtle compositing back the way it was drawTurtle = save; return self; } - save:sender // Called when Save is picked from the menu. { return [self _doSaveWithNewName:NO retainName:YES]; } - saveAs:sender // Called when Save As... is picked from the menu. { return [self _doSaveWithNewName:YES retainName:YES]; } - saveTo:sender // Called when Save To... is picked from the menu. { return [self _doSaveWithNewName:YES retainName:NO]; } - add:sender // Action method, called when the user chooses add in the menu. { return [self _open:sender _newDrawing:NO]; } - open:sender // Action method, called when the user chooses open in the menu. { return [self _open:sender _newDrawing:YES]; } - _open:sender _newDrawing:(BOOL)doClear // This is used for both open and add. // The doClear variable says whether to add to or clear the drawing. { const char *const *file; static const char *const fileType[2] = {"logo", NULL}; id openPanel; char fullName[MAXPATHLEN]; // Run the open panel, filtering for out type of document openPanel = [OpenPanel new]; if ([openPanel runModalForTypes:fileType]) { // Open the file returned by the open panel file = [openPanel filenames]; // Need to piece together the name from filenames and directory calls. strcpy(fullName, [openPanel directory]); strcat(fullName, "/"); strcat(fullName, *file); if(doClear) name = fullName; [self _read:fullName _newDrawing:doClear]; } return self; } - _doSaveWithNewName:(BOOL)doNewName retainName:(BOOL)doRetain { id savePanel; // filename to save into const char *saveName; NXZone *zone; // If the file is untitled or we are saving under a different name, // run the save panel to get a new name. zone = [self zone]; if (!name || doNewName) { savePanel = [SavePanel new]; [savePanel setRequiredFileType:"logo"]; if ([savePanel runModalForDirectory:NULL file:name]) { // If we want to keep this name, replace any old name. if (doRetain) { NXZoneFree(zone, name); name = NXCopyStringBufferFromZone([savePanel filename], zone); } saveName = [savePanel filename]; } else return self; } else // if we didn't run the Save Panel, save using the existing name. saveName = name; // Now do a _write routine. [self _write:saveName]; return self; } - _write:(const char *)filename // Writes a document to the given file using typedstreams. { NXTypedStream *ts; float realVal; struct prStruct *tempStruct = &firstStruct; int howMany = 0; // Open the typed stream to a file for writing. ts = NXOpenTypedStreamForFile(filename, NX_WRITEONLY); if (ts) { // Version of this write's data. realVal = 1.0; NXWriteType(ts, "f", &realVal); // Figure out how many lines there are. while(tempStruct->nextStruct != NULL) { howMany++; tempStruct = tempStruct->nextStruct; } // Now save that number for the reading in of the file. /* NXWriteType(ts, "i", &howMany); */ tempStruct = &firstStruct; // Continue by writing out all the lines. for(NXWriteType(ts,"i", &howMany);howMany >= 0;howMany--) { NXWriteArray(ts, "f", 4, tempStruct->oArray); NXWriteArray(ts, "c", 4, tempStruct->cArray); tempStruct = tempStruct->nextStruct; } // Close the stream. All done. NXCloseTypedStream(ts); } return self; } - _read:(const char *)filename _newDrawing:(BOOL)doClear // Reads a document from the given file using typedstreams. { NXTypedStream *ts; float realVal; int howMany = 0; // Open the typed stream as a file. ts = NXOpenTypedStreamForFile(filename, NX_READONLY); if (ts) { // If this is an open the drawing needs to be cleared. if(doClear) [self clearScreen]; // The version number is not used as of this version // but it needs to be retrieved anyway. NXReadType(ts, "f", &realVal); // This next variable is used to find out how many lines // need to be added. NXReadType(ts, "i", &howMany); // Get howMany lines and add them into the drawing link list. for(;howMany >= 1;howMany--) { NXReadArray(ts, "f", 4, thisStruct->oArray); NXReadArray(ts, "c", 4, thisStruct->cArray); thisStruct->nextStruct = (struct prStruct *)malloc(sizeof(struct prStruct)); thisStruct = thisStruct->nextStruct; thisStruct->nextStruct = NULL; } // Close the typed stream (file) NXCloseTypedStream(ts); // Tell the image to clear the image and that we want to // redraw it when the next composite is called. [idBackground recache]; } return [self display]; } - new:sender { // All we need to do is clear the screen for a new. return [self clearScreen]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.