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;
}
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.