home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / MiniExamples / ImageText / GraphicImage.m < prev    next >
Encoding:
Text File  |  1992-12-19  |  5.9 KB  |  220 lines

  1. // GraphicImage.m
  2. // By Jayson Adams
  3. // NeXT Strategic Developer Engineer
  4. //
  5. // You may freely copy, distribute and reuse the code in this example.
  6. // NeXT disclaims any warranty of any kind, expressed or implied, as to its
  7. // fitness for any particular use.
  8.  
  9. #import <dpsclient/psops.h>
  10. #import <dpsclient/wraps.h>
  11. #import <appkit/NXImage.h>
  12. #import <appkit/Text.h>
  13. #import <appkit/Window.h>
  14. #import <appkit/Application.h>
  15.  
  16. #import "Controller.h"
  17.  
  18. #import "GraphicImage.h"
  19.  
  20.  
  21. @implementation GraphicImage
  22.  
  23.  
  24. - initForImage:anImage
  25. {
  26.     [super init];
  27.     
  28.   /* save our graphic image */
  29.     image = anImage;
  30.     
  31.     return self;
  32. }
  33.  
  34. - free
  35. {
  36.     [image free];
  37.     return [super free];
  38. }
  39.  
  40. - calcCellSize:(NXSize *)theSize
  41. {
  42.   /* our graphic image determines our size */
  43.     [image getSize:theSize];
  44.  
  45.     return self;
  46. }
  47.  
  48. - highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag
  49. {
  50.     if (highlighted != flag) {
  51.     highlighted = flag;
  52.     
  53.       /* toggle highlighting */
  54.     NXHighlightRect(cellFrame);
  55.     
  56.       /* make change visible */
  57.     [[controlView window] flushWindow];
  58.     }
  59.     
  60.     return self;
  61. }
  62.  
  63. - drawSelf:(const NXRect *)cellFrame inView:controlView
  64. {
  65.     NXPoint    point;
  66.     
  67.   /*
  68.    * the text object expects us not to modify the current graphics state, so
  69.    * we'll save it
  70.    */
  71.     PSgsave();
  72.  
  73.   /* clear our rect using the text object's background gray and transparancy */
  74.     PSsetgray([controlView backgroundGray]);
  75.     if ([controlView isOpaque]) {
  76.         PSsetalpha(1);
  77.     } else {
  78.         PSsetalpha(0);
  79.     }
  80.     NXRectFill(cellFrame);
  81.     
  82.   /* we're in a flipped coordinate system */
  83.     point = cellFrame->origin;
  84.     point.y += cellFrame->size.height;
  85.     
  86.   /* draw the image */
  87.     [image composite:NX_SOVER toPoint:&point];
  88.     
  89.   /* restore the graphics state */
  90.     PSgrestore();
  91.  
  92.     return self;
  93. }
  94.  
  95. #define DRAG_MASK (NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK)
  96.  
  97. - trackMouse:(NXEvent *)theEvent inRect:(const NXRect *)cellFrame
  98.   ofView:controlView
  99. {
  100.     int        oldMask;
  101.     NXEvent    *event;
  102.     NXPoint    mouseLocation;
  103.     BOOL    mouseInCell = NO;
  104.     
  105.   /* we want to grab mouse dragged events */
  106.     oldMask = [[controlView window] addToEventMask:NX_MOUSEDRAGGEDMASK];
  107.     
  108.   /* start our event loop, looking for mouse-dragged or mouse-up events */
  109.     event = [NXApp getNextEvent:DRAG_MASK];
  110.     while (event->type != NX_MOUSEUP) {
  111.  
  112.       /* mouse-dragged event;  highlight if mouse is in cell bounds */
  113.     mouseLocation = event->location;
  114.     [controlView convertPoint:&mouseLocation fromView:NULL];
  115.     mouseInCell = NXPointInRect(&mouseLocation, cellFrame);
  116.     
  117.     if (mouseInCell != highlighted) {
  118.       /* we have to lock focus before calling hightlight:inView:lit: */
  119.         [controlView lockFocus];
  120.         [self highlight:cellFrame inView:controlView lit:mouseInCell];
  121.         [controlView unlockFocus];
  122.     }
  123.     event = [NXApp getNextEvent:DRAG_MASK];
  124.     }
  125.     
  126.   /* turn off any highlighting */
  127.     [controlView lockFocus];
  128.     [self highlight:cellFrame inView:controlView lit:NO];
  129.     [controlView unlockFocus];
  130.     
  131.   /* reset the event mask */
  132.     [[controlView window] setEventMask:oldMask];
  133.     
  134.   /* if a double-click and the mouse is over us, do something */
  135.     mouseLocation = event->location;
  136.     [controlView convertPoint:&mouseLocation fromView:NULL];
  137.     if (NXPointInRect(&mouseLocation, cellFrame) &&
  138.         event->data.mouse.click == 2) {
  139.     [self performDoubleClickAction];
  140.     }
  141.     
  142.     return self;
  143. }
  144.  
  145. - readRichText:(NXStream *)stream forView:view
  146. {
  147.     NXStream    *memoryStream;
  148.     int        length, i = 0;
  149.     char    highNibble, lowNibble;
  150.     
  151.   /* find out how bytes there are */
  152.     NXScanf(stream, "%d ", &length);
  153.     
  154.   /* create a place to temporarily store the reconstituted image data */
  155.     memoryStream = NXOpenMemory(NULL, 0, NX_READWRITE);
  156.     while (i < length) {
  157.         highNibble = NXGetc(stream) - ' ';
  158.         lowNibble = NXGetc(stream) - ' ';
  159.     NXPutc(memoryStream, ((highNibble << 4) + lowNibble));
  160.     i++;
  161.     }
  162.     
  163.   /* rewind and feed the data to our NXImage */
  164.     NXSeek(memoryStream, 0, NX_FROMSTART);
  165.     image = [[NXImage alloc] initFromStream:memoryStream];
  166.  
  167.     NXCloseMemory(memoryStream, NX_FREEBUFFER);
  168.  
  169.     return self;
  170. }
  171.  
  172. - writeRichText:(NXStream *)stream forView:view
  173. {
  174.     NXStream    *memoryStream;
  175.     char    nextByte, *buffer;
  176.     int        length, maxLength, i;
  177.     
  178.   /*
  179.    * This method gives us a chance to write out whatever information we
  180.    * need to recreate ourself when the text object loads the RTF back in.
  181.    * There are a couple different strategies for doing this:  placing the
  182.    * data "inline" or writing out the filename and saving the file somewhere
  183.    * else.  This method takes the first approach, converting the TIFF data to
  184.    * ASCII (7-bits) since the RTF specification requires 8-bit data to be
  185.    * escaped.  This isn't the best solution because every time we read the RTF
  186.    * file in, we have to read the data as well (which we've expanded to twice
  187.    * its original size in order to store in the RTF).  Additionally, the data's
  188.    * imbedded within the RTF (there might be occassions where we want to read
  189.    * the data, a TIFF in this case, but not the RTF).  The best approach is to
  190.    * place the data in a BTree or some other external storage and to leave some
  191.    * identifier in the RTF stream.
  192.    */
  193.  
  194.   /* get some temporary storage */
  195.     memoryStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  196.     [image writeTIFF:memoryStream];
  197.  
  198.   /* get a pointer to the TIFF data and remember its length in bytes */
  199.     NXGetMemoryBuffer(memoryStream, &buffer, &length, &maxLength);
  200.     NXPrintf(stream, "%d ", length);
  201.  
  202.   /* convert each byte to two ASCII characters */
  203.     for (i = 0; i < length; i++) {
  204.         nextByte = buffer[i];
  205.         NXPrintf(stream, "%c%c", ((nextByte & 0xF0) >> 4) + ' ',
  206.          (nextByte & 0x0F) + ' ');
  207.     }
  208.     
  209.     NXCloseMemory(memoryStream, NX_FREEBUFFER);
  210.     
  211.     return self;
  212. }
  213.  
  214. - performDoubleClickAction
  215. {
  216.   /* we don't do anything when the user double-clicks on us */
  217.     return self;
  218. }
  219.  
  220. @end