home *** CD-ROM | disk | FTP | other *** search
/ Nebula / nebula.bin / SourceCode / MiniExamples / ImageText / Controller.m < prev    next >
Text File  |  1993-01-19  |  6KB  |  252 lines

  1. // Controller.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 <libc.h>            // for strcmp(), index(), rindex()
  10. #import <streams/streams.h>
  11. #import <appkit/publicWraps.h>        // for NXConvertWinNumToGlobal()
  12. #import <appkit/Control.h>
  13. #import <appkit/NXImage.h>
  14. #import <appkit/ScrollView.h>
  15. #import <appkit/Text.h>
  16. #import <appkit/Listener.h>
  17. #import <appkit/Speaker.h>
  18. #import <appkit/Window.h>
  19. #import <appkit/OpenPanel.h>
  20. #import <appkit/SavePanel.h>
  21. #import <appkit/Application.h>
  22.  
  23. #import "CopyIcon.h"
  24. #import "FileImage.h"
  25. #import "GraphicImage.h"
  26.  
  27. #import "Controller.h"
  28.  
  29.  
  30. @implementation Controller
  31.  
  32.  
  33. /* instance methods */
  34.  
  35. - appDidInit:sender
  36. {
  37.     [Text registerDirective:"FileImage" forClass:[FileImage class]];
  38.     [Text registerDirective:"GraphicImage" forClass:[GraphicImage class]];
  39.     
  40.     [self registerWindow];
  41.     
  42.     [textObj setSel:0 :0];
  43.     
  44.     return self;
  45. }
  46.  
  47. - registerWindow
  48. {
  49.     unsigned int    windowNum;
  50.     id            speaker;
  51.     
  52.   /* register our app icon window with the workspace */
  53.     NXConvertWinNumToGlobal([[textObj window] windowNum], &windowNum);
  54.     speaker = [NXApp appSpeaker];
  55.     [speaker setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
  56.     [speaker registerWindow:windowNum
  57.              toPort:[[NXApp appListener] listenPort]];
  58.  
  59.     return self;
  60. }
  61.  
  62. static BOOL isEPSOrTIFF(char *filePath)
  63. {
  64.     char    *extension;
  65.     
  66.     if (!(extension = rindex(filePath, '.'))) {
  67.         return NO;
  68.     }
  69.     return (!strcmp(".eps", extension) || !strcmp(".tiff", extension));
  70. }
  71.  
  72. - (int)iconEntered:(int)windowNum at:(double)x :(double)y
  73.     iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY
  74.     iconWidth:(double)iconWidth iconHeight:(double)iconHeight
  75.     pathList:(char *)pathList
  76. {
  77.     char    *stringPosition;
  78.     int        files=1;
  79.     id        newImage, newGraphic;
  80.     NXSize    size = {48.0, 48.0};
  81.     struct stat statData;
  82.         
  83.   /* the number of tabs + 1 equals the number of files dragged in */
  84.     stringPosition = pathList;
  85.     while (stringPosition = index(stringPosition, '\t')) {
  86.         files++;
  87.         stringPosition++;
  88.     }
  89.     
  90.   /* make sure the user dragged one file in (and it wasn't root) */
  91.     if ((files > 1) || !(*pathList)) {
  92.     acceptedIcon = NO;
  93.     return 0;
  94.     }
  95.     
  96.   /* punt if a directory */
  97.     stat(pathList, &statData);
  98.     if (statData.st_mode & S_IFDIR) {
  99.         acceptedIcon = NO;
  100.     return 0;
  101.     }
  102.     
  103.     acceptedIcon = YES;
  104.     
  105.     if (isEPSOrTIFF(pathList)) {
  106.       /* copy the tiff or eps image into the text object */
  107.     newImage = [[NXImage alloc] initFromFile:pathList];
  108.     newGraphic = [[GraphicImage alloc] initForImage:newImage];
  109.     [textObj replaceSelWithCell:newGraphic];
  110.     } else {
  111.      /*
  112.       * use some PostScript code to copy the bits from the Workspace
  113.       * window into our NXImage
  114.       */
  115.     newImage = [[NXImage alloc] initSize:&size];
  116.     if ([newImage lockFocus]) {
  117.         copyIconPicture(iconWindowNum, iconX, iconY, iconWidth,
  118.                     iconHeight);
  119.         [newImage unlockFocus];
  120.         newGraphic = [[FileImage alloc] initForImage:newImage
  121.                          fileName:pathList];
  122.         [textObj replaceSelWithCell:newGraphic];
  123.     }
  124.     }
  125.     
  126.     return 0;
  127. }
  128.  
  129. - (int)iconExitedAt:(double)x :(double)y
  130. {
  131.     NXSelPt    start, end;
  132.     
  133.     if (acceptedIcon) {
  134.     [[textObj getSel:&start :&end] setSel:start.cp - 1 :start.cp];
  135.     [textObj replaceSel:""];
  136.     }
  137.     
  138.     return 0;
  139. }
  140.  
  141. - (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag
  142. {
  143.     if (acceptedIcon) {
  144.         *flag = 1;
  145.     } else {
  146.         *flag = 0;
  147.     }
  148.  
  149.     return 0;
  150. }
  151.  
  152. - lipService:sender
  153. {
  154.     id        uniqueLipImage, lips;
  155.     
  156.   /* 
  157.    * we could use findImageNamed: to get the image, but it always returns the
  158.    * same instance for a given name.  This causes problems when we have two
  159.    * graphicImages using the lips icon 'cause when they get freed, they both
  160.    * free the same nximage (and the app crashes).  We can't do something like
  161.    * [[NXImage findImageNamed:"lips"] copy] 'cause the copy method only
  162.    * duplicates the nximage, not any of its representations.  Using 
  163.    * initFromSection: is a reasonable workaround.
  164.    */
  165.     uniqueLipImage = [[NXImage alloc] initFromSection:"lips.tiff"];
  166.     
  167.     lips = [[GraphicImage alloc] initForImage:uniqueLipImage];
  168.     [textObj replaceSelWithCell:lips];
  169.     
  170.     return self;
  171. }
  172.  
  173. #define OPEN 1
  174. #define OPEN_RTF_AS_ASCII 2
  175.  
  176. - open:sender
  177. {
  178.     id        openPanel;
  179.     NXStream    *stream;
  180.     const char    *types[2] = {"rtf", NULL};
  181.     
  182.     openPanel = [OpenPanel new];
  183.     [openPanel allowMultipleFiles:NO];
  184.     
  185.     if ([openPanel runModalForTypes:types]) {
  186.     stream = NXMapFile([openPanel filename], NX_READONLY);
  187.     if ([[sender selectedCell] tag] == OPEN_RTF_AS_ASCII) {
  188.         [textObj readText:stream];
  189.     } else {
  190.         [textObj readRichText:stream];
  191.     }
  192.     NXCloseMemory(stream, NX_FREEBUFFER);
  193.     [textObj setSel:0 :0];
  194.     }
  195.     
  196.     return self;
  197. }
  198.  
  199. - save:sender
  200. {
  201.     id        savePanel;
  202.     NXStream    *stream;
  203.     
  204.     savePanel = [SavePanel new];
  205.     [savePanel setRequiredFileType:"rtf"];
  206.     
  207.     if ([savePanel runModal]) {
  208.         stream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  209.     [textObj writeRichText:stream];
  210.     if (NXSaveToFile(stream, [savePanel filename]) == -1) {
  211.         NXRunAlertPanel(NULL, "Couldn't write file", NULL, NULL, NULL);
  212.     }
  213.     NXCloseMemory(stream, NX_FREEBUFFER);
  214.     }
  215.     
  216.     return self;
  217. }
  218.  
  219. - windowWillResize:sender toSize:(NXSize *)frameSize
  220. {
  221.     if (frameSize->height < 200.0) {
  222.         frameSize->height = 200.0;
  223.     }
  224.     
  225.     if (frameSize->width < 200.0) {
  226.         frameSize->width = 200.0;
  227.     }
  228.     return self;
  229. }
  230.  
  231. - info:sender
  232. {
  233.     if (!infoPanel) {
  234.         [NXApp loadNibSection:"Info.nib" owner:self];
  235.     }
  236.     
  237.     [infoPanel makeKeyAndOrderFront:NULL];
  238.     
  239.     return self;
  240. }
  241.  
  242.  
  243. /* outlet initialization */
  244.  
  245. - setScrollView:anObject
  246. {
  247.     scrollView = anObject;
  248.     textObj = [scrollView docView];
  249.     return self;
  250. }
  251.  
  252. @end