home *** CD-ROM | disk | FTP | other *** search
- // 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();
-
- /* clear our rect using the text object's background gray and transparancy */
- PSsetgray([controlView backgroundGray]);
- if ([controlView isOpaque]) {
- PSsetalpha(1);
- } else {
- PSsetalpha(0);
- }
- 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