This is GraphicImage.m in view mode; [Download] [Up]
// GraphicImage.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 <dpsclient/psops.h> #import <dpsclient/wraps.h> #import <appkit/NXImage.h> #import <appkit/Text.h> #import <appkit/Window.h> #import <appkit/Application.h> #import "Controller.h" #import "GraphicImage.h" @implementation GraphicImage - initForImage:anImage { [super init]; /* save our graphic image */ image = anImage; return self; } - free { [image free]; return [super free]; } - calcCellSize:(NXSize *)theSize { /* our graphic image determines our size */ [image getSize:theSize]; return self; } - highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag { if (highlighted != flag) { highlighted = flag; /* toggle highlighting */ NXHighlightRect(cellFrame); /* make change visible */ [[controlView window] flushWindow]; } return self; } - drawSelf:(const NXRect *)cellFrame inView:controlView { NXPoint point; /* * the text object expects us not to modify the current graphics state, so * we'll save it */ PSgsave(); /* fill our bounds with the text object's background gray (if opaque) */ if ([controlView isOpaque]) { PSsetgray([controlView backgroundGray]); NXRectFill(cellFrame); } /* we're in a flipped coordinate system */ point = cellFrame->origin; point.y += cellFrame->size.height; /* draw the image */ [image composite:NX_SOVER toPoint:&point]; /* restore the graphics state */ PSgrestore(); return self; } #define DRAG_MASK (NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK) - trackMouse:(NXEvent *)theEvent inRect:(const NXRect *)cellFrame ofView:controlView { int oldMask; NXEvent *event; NXPoint mouseLocation; BOOL mouseInCell = NO; /* we want to grab mouse dragged events */ oldMask = [[controlView window] addToEventMask:NX_MOUSEDRAGGEDMASK]; /* start our event loop, looking for mouse-dragged or mouse-up events */ event = [NXApp getNextEvent:DRAG_MASK]; while (event->type != NX_MOUSEUP) { /* mouse-dragged event; highlight if mouse is in cell bounds */ mouseLocation = event->location; [controlView convertPoint:&mouseLocation fromView:NULL]; mouseInCell = NXPointInRect(&mouseLocation, cellFrame); if (mouseInCell != highlighted) { /* we have to lock focus before calling hightlight:inView:lit: */ [controlView lockFocus]; [self highlight:cellFrame inView:controlView lit:mouseInCell]; [controlView unlockFocus]; } event = [NXApp getNextEvent:DRAG_MASK]; } /* turn off any highlighting */ [controlView lockFocus]; [self highlight:cellFrame inView:controlView lit:NO]; [controlView unlockFocus]; /* reset the event mask */ [[controlView window] setEventMask:oldMask]; /* if a double-click and the mouse is over us, do something */ mouseLocation = event->location; [controlView convertPoint:&mouseLocation fromView:NULL]; if (NXPointInRect(&mouseLocation, cellFrame) && event->data.mouse.click == 2) { [self performDoubleClickAction]; } return self; } - readRichText:(NXStream *)stream forView:view { NXStream *memoryStream; int length, i = 0; char highNibble, lowNibble; /* find out how bytes there are */ NXScanf(stream, "%d ", &length); /* create a place to temporarily store the reconstituted image data */ memoryStream = NXOpenMemory(NULL, 0, NX_READWRITE); while (i < length) { highNibble = NXGetc(stream) - ' '; lowNibble = NXGetc(stream) - ' '; NXPutc(memoryStream, ((highNibble << 4) + lowNibble)); i++; } /* rewind and feed the data to our NXImage */ NXSeek(memoryStream, 0, NX_FROMSTART); image = [[NXImage alloc] initFromStream:memoryStream]; NXCloseMemory(memoryStream, NX_FREEBUFFER); return self; } - writeRichText:(NXStream *)stream forView:view { NXStream *memoryStream; char nextByte, *buffer; int length, maxLength, i; /* * This method gives us a chance to write out whatever information we * need to recreate ourself when the text object loads the RTF back in. * There are a couple different strategies for doing this: placing the * data "inline" or writing out the filename and saving the file somewhere * else. This method takes the first approach, converting the TIFF data to * ASCII (7-bits) since the RTF specification requires 8-bit data to be * escaped. This isn't the best solution because every time we read the RTF * file in, we have to read the data as well (which we've expanded to twice * its original size in order to store in the RTF). Additionally, the data's * imbedded within the RTF (there might be occassions where we want to read * the data, a TIFF in this case, but not the RTF). The best approach is to * place the data in a BTree or some other external storage and to leave some * identifier in the RTF stream. */ /* get some temporary storage */ memoryStream = NXOpenMemory(NULL, 0, NX_WRITEONLY); [image writeTIFF:memoryStream]; /* get a pointer to the TIFF data and remember its length in bytes */ NXGetMemoryBuffer(memoryStream, &buffer, &length, &maxLength); NXPrintf(stream, "%d ", length); /* convert each byte to two ASCII characters */ for (i = 0; i < length; i++) { nextByte = buffer[i]; NXPrintf(stream, "%c%c", ((nextByte & 0xF0) >> 4) + ' ', (nextByte & 0x0F) + ' '); } NXCloseMemory(memoryStream, NX_FREEBUFFER); return self; } - performDoubleClickAction { /* we don't do anything when the user double-clicks on us */ return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.