home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / SoundApps / Patchmix / Source / TransparentWindow.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  7.3 KB  |  253 lines

  1. // TransparentWindow.m
  2. // By Jayson Adams, NeXT Developer Support Team
  3. // You may freely copy, distribute and reuse the code in this example.
  4. // NeXT disclaims any warranty of any kind, expressed or implied, as to its
  5. // fitness for any particular use.
  6.  
  7. #import <math.h>
  8. #import <dpsclient/wraps.h>
  9. #import <appkit/publicWraps.h>
  10. #import <appkit/NXImage.h>
  11. #import <appkit/Window.h>
  12. #import <appkit/Application.h>
  13.  
  14. #import "pswraps.h"
  15. #import "PatchWindow.h"
  16. #import "Animator.h"
  17.  
  18. #import "TransparentWindow.h"
  19.  
  20.  
  21. #define NOWINDOW 0
  22.  
  23.  
  24. @implementation TransparentWindow
  25.  
  26.  
  27. - initForImage:anImage at:(NXPoint *)windowOrigin forView:anObject
  28. {
  29.     NXRect    windowFrame;
  30.     NXPoint    origin = {0.0, 0.0};
  31.     
  32.   /*
  33.    * create an offscreen window with the image (for use in our pswrap routines)
  34.    */
  35.     [anImage getSize:&windowSize];
  36.     windowFrame.origin.x = windowFrame.origin.y = 0.0;
  37.     windowFrame.size = windowSize;
  38.     image = [[Window alloc] initContent:&windowFrame
  39.                 style:NX_PLAINSTYLE
  40.                 backing:NX_RETAINED
  41.                 buttonMask:0
  42.                 defer:NO];
  43.  
  44.   /* copy the image to our new window */
  45.     [[image contentView] lockFocus];
  46.     [anImage composite:NX_COPY toPoint:&origin];
  47.     [[image contentView] unlockFocus];
  48.     
  49.   /* save the object that created us */
  50.     source = anObject;
  51.     
  52.   /*
  53.    * create an animator to move our transparent window back to its origin if
  54.    * the user lets go of the window over something that won't accept it;  we'll
  55.    * create it now so there's no delay when we really need it
  56.    */
  57.     animator = [[Animator alloc] initChronon:(1.0 / 40.0)
  58.                  adaptation:0.0
  59.                  target:self
  60.                  action:@selector(animateBack:)
  61.                  autoStart:NO
  62.                  eventMask:0];
  63.                  
  64.     return self;
  65. }
  66.  
  67. - free
  68. {
  69.     [image free];
  70.     [animator free];
  71.     
  72.     return [super free];
  73. }
  74.  
  75. - image
  76. {
  77.     return image;
  78. }
  79.  
  80. - dragFromMouseDown:(NXPoint *)startingPoint mouseOffset:(NXPoint *)offset
  81. {
  82.     int            mouseUp = 0, windowUnderImage, windowUnderMouseChanged = 0,
  83.             previousWindowUnderMouseChanged = 0;
  84.     unsigned int    windowNum;
  85.     BOOL        accepted = NO;
  86.     float        deltaX, deltaY, distance;
  87.     
  88.   /* disable the wait cursor for our dragging loop */
  89.     PSsetwaitcursorenabled(NO);
  90.  
  91.   /* get the image's gstate for our dragWindow pswrap */
  92.     imageGstate = [image gState];
  93.     
  94.     currentPoint = stoppingPoint = *startingPoint;
  95.     
  96.   /* set everything up for the drag loop */
  97.     initDrag(currentPoint.x, currentPoint.y, offset->x, offset->y,
  98.              windowSize.width, windowSize.height, &iWindow, &bgWindow,
  99.          &niWindow, &igstate, &bggstate, &nigstate, &gWindow, &ggstate);
  100.  
  101.     while (!mouseUp) {
  102.       /* call the pswrap that moves the transparent window */
  103.     dragWindow(iWindow, niWindow, gWindow, windowUnderMouseChanged,
  104.                  previousWindowUnderMouseChanged, igstate, bggstate,
  105.            nigstate, imageGstate, ggstate, currentPoint.x,
  106.            currentPoint.y, offset->x, offset->y, windowSize.width,
  107.            windowSize.height, &mouseUp, &windowUnderImage,
  108.            &(currentPoint.x), &(currentPoint.y));
  109.  
  110.     [self checkForAcceptWindow:windowUnderImage
  111.           atPoint:¤tPoint
  112.                    :&windowUnderMouseChanged
  113.              :&previousWindowUnderMouseChanged];
  114.     }
  115.  
  116.   /*
  117.    * flush window's because checkForAcceptWindow might've caused windows to
  118.    * change and the user may have let go of the mouse, making mouseUp true and
  119.    * preventing dragWindow from getting called (which does the flushWindows
  120.    * normally)
  121.    */
  122.     if (windowUnderMouseChanged) {
  123.     NXConvertGlobalToWinNum(windowUnderMouseChanged, &windowNum);
  124.     [[NXApp findWindow:windowNum] flushWindow];
  125.     }
  126.  
  127.   /*
  128.    * if there was a window under the mouse point, flush it for the reasons
  129.    * above, plus tell it the user dropped the image on it
  130.    */
  131.     if (previousWindowUnderMouse) {
  132.     if (previousWindowUnderMouseChanged) {
  133.         [previousWindowUnderMouse flushWindow];
  134.     }
  135.     accepted = [previousWindowUnderMouse windowDropped:¤tPoint
  136.                          fromSource:source];
  137.     }
  138.     
  139.   /* turn the wait cursor back on */
  140.     PSsetwaitcursorenabled(YES);
  141.     
  142.   /*
  143.    * if the user didn't drop the window over an accepting window, or the
  144.    * window didn't accept it, animate the transparent window back to its origin
  145.    */
  146.     if (!accepted) {
  147.     deltaX = currentPoint.x - startingPoint->x;
  148.     deltaY = currentPoint.y - startingPoint->y;
  149.     if (deltaX && deltaY) {
  150.         distance = sqrt(deltaX  * deltaX + deltaY * deltaY);
  151.         frames = ceil(40.0 * distance / 5000.0);
  152.         if (frames == 1) {
  153.           /* make an exception for windows close to their origin */
  154.         frames = ceil(40.0 * distance / 1400.0);
  155.         }
  156.         increment.x = deltaX / frames;
  157.         increment.y = deltaY / frames;
  158.     
  159.       /* we need to remember the mouse offset */
  160.         mouseOffset = *offset;
  161.         [animator startEntry];
  162.         
  163.         return self;
  164.     }
  165.     }
  166.     
  167.   /* destroy the windows and gstates used to drag the TransparentWindow */
  168.     cleanup(iWindow, bgWindow, niWindow, gWindow, igstate, bggstate, nigstate,
  169.             ggstate);
  170.     
  171.     return [self free];
  172. }
  173.  
  174. - animateBack:sender
  175. {
  176.   /* compute the transparent window's new location */
  177.     currentPoint.x -= increment.x;
  178.     currentPoint.y -= increment.y;
  179.     
  180.   /* see if new location is close enough to the final position */
  181.     if ((increment.x > 0 && (currentPoint.x < stoppingPoint.x + 3.0)) ||
  182.       (increment.x < 0 && (currentPoint.x > stoppingPoint.x - 3.0))) {
  183.     currentPoint.x = stoppingPoint.x;
  184.     }
  185.     if ((increment.y > 0 && (currentPoint.y < stoppingPoint.y + 3.0)) ||
  186.       (increment.y < 0 && (currentPoint.y > stoppingPoint.y + 3.0))) {
  187.     currentPoint.y = stoppingPoint.y;
  188.     }
  189.  
  190.   /* move it there */
  191.     miniDragWindow(iWindow, niWindow, gWindow, igstate, bggstate, nigstate,
  192.                imageGstate, ggstate, currentPoint.x, currentPoint.y,
  193.            mouseOffset.x, mouseOffset.y, windowSize.width,
  194.            windowSize.height);
  195.     
  196.   /* count down the number of frames */
  197.     if (--frames) {
  198.     return self;
  199.     }
  200.     
  201.   /* all done */
  202.     [animator stopEntry];
  203.     cleanup(iWindow, bgWindow, niWindow, gWindow, igstate, bggstate, nigstate,
  204.             ggstate);
  205.     
  206.     return [self free];
  207. }
  208.  
  209. - checkForAcceptWindow:(int)windowNumUnderMouse atPoint:(NXPoint *)point
  210.   :(int *)windowUnderMouseChanged :(int *)previousWindowUnderMouseChanged
  211. {
  212.     unsigned   int    windowNum;
  213.     id            windowUnderMouse = NOWINDOW;
  214.     
  215.     *windowUnderMouseChanged = 0;
  216.     *previousWindowUnderMouseChanged = 0;
  217.       
  218.   /* find the window object under the mouse point */
  219.     if (windowNumUnderMouse) {
  220.     NXConvertGlobalToWinNum(windowNumUnderMouse, &windowNum);
  221.     windowUnderMouse = [NXApp findWindow:windowNum];
  222.     if (![windowUnderMouse
  223.                respondsTo:@selector(windowEntered:fromSource:)]) {
  224.         windowUnderMouse = NOWINDOW;
  225.         windowNumUnderMouse = 0;
  226.     }
  227.     }
  228.     
  229.   /*
  230.    * tell the window previously under the mouse (if different) that the image
  231.    * exited
  232.    */
  233.     if (windowUnderMouse != previousWindowUnderMouse &&
  234.     previousWindowUnderMouse != NOWINDOW) {
  235.     if ([previousWindowUnderMouse windowExited:source]) {
  236.         *previousWindowUnderMouseChanged = previousWindowNumUnderMouse;
  237.     }
  238.     }
  239.     
  240.   /* tell the window under the mouse (if it exists) that the image entered */
  241.     if (windowUnderMouse != NOWINDOW) {
  242.     if ([windowUnderMouse windowEntered:point fromSource:source]) {
  243.         *windowUnderMouseChanged = windowNumUnderMouse;
  244.     }
  245.     }
  246.     
  247.     previousWindowUnderMouse = windowUnderMouse;
  248.     previousWindowNumUnderMouse = windowNumUnderMouse;
  249.     
  250.     return self;
  251. }
  252.  
  253. @end