This is TransparentWindow.m in view mode; [Download] [Up]
// TransparentWindow.m // By Jayson Adams, NeXT Developer Support Team // 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 <math.h> #import <dpsclient/wraps.h> #import <appkit/publicWraps.h> #import <appkit/NXImage.h> #import <appkit/Window.h> #import <appkit/Application.h> #import "pswraps.h" #import "PatchWindow.h" #import "Animator.h" #import "TransparentWindow.h" #define NOWINDOW 0 @implementation TransparentWindow - initForImage:anImage at:(NXPoint *)windowOrigin forView:anObject { NXRect windowFrame; NXPoint origin = {0.0, 0.0}; /* * create an offscreen window with the image (for use in our pswrap routines) */ [anImage getSize:&windowSize]; windowFrame.origin.x = windowFrame.origin.y = 0.0; windowFrame.size = windowSize; image = [[Window alloc] initContent:&windowFrame style:NX_PLAINSTYLE backing:NX_RETAINED buttonMask:0 defer:NO]; /* copy the image to our new window */ [[image contentView] lockFocus]; [anImage composite:NX_COPY toPoint:&origin]; [[image contentView] unlockFocus]; /* save the object that created us */ source = anObject; /* * create an animator to move our transparent window back to its origin if * the user lets go of the window over something that won't accept it; we'll * create it now so there's no delay when we really need it */ animator = [[Animator alloc] initChronon:(1.0 / 40.0) adaptation:0.0 target:self action:@selector(animateBack:) autoStart:NO eventMask:0]; return self; } - free { [image free]; [animator free]; return [super free]; } - image { return image; } - dragFromMouseDown:(NXPoint *)startingPoint mouseOffset:(NXPoint *)offset { int mouseUp = 0, windowUnderImage, windowUnderMouseChanged = 0, previousWindowUnderMouseChanged = 0; unsigned int windowNum; BOOL accepted = NO; float deltaX, deltaY, distance; /* disable the wait cursor for our dragging loop */ PSsetwaitcursorenabled(NO); /* get the image's gstate for our dragWindow pswrap */ imageGstate = [image gState]; currentPoint = stoppingPoint = *startingPoint; /* set everything up for the drag loop */ initDrag(currentPoint.x, currentPoint.y, offset->x, offset->y, windowSize.width, windowSize.height, &iWindow, &bgWindow, &niWindow, &igstate, &bggstate, &nigstate, &gWindow, &ggstate); while (!mouseUp) { /* call the pswrap that moves the transparent window */ dragWindow(iWindow, niWindow, gWindow, windowUnderMouseChanged, previousWindowUnderMouseChanged, igstate, bggstate, nigstate, imageGstate, ggstate, currentPoint.x, currentPoint.y, offset->x, offset->y, windowSize.width, windowSize.height, &mouseUp, &windowUnderImage, &(currentPoint.x), &(currentPoint.y)); [self checkForAcceptWindow:windowUnderImage atPoint:¤tPoint :&windowUnderMouseChanged :&previousWindowUnderMouseChanged]; } /* * flush window's because checkForAcceptWindow might've caused windows to * change and the user may have let go of the mouse, making mouseUp true and * preventing dragWindow from getting called (which does the flushWindows * normally) */ if (windowUnderMouseChanged) { NXConvertGlobalToWinNum(windowUnderMouseChanged, &windowNum); [[NXApp findWindow:windowNum] flushWindow]; } /* * if there was a window under the mouse point, flush it for the reasons * above, plus tell it the user dropped the image on it */ if (previousWindowUnderMouse) { if (previousWindowUnderMouseChanged) { [previousWindowUnderMouse flushWindow]; } accepted = [previousWindowUnderMouse windowDropped:¤tPoint fromSource:source]; } /* turn the wait cursor back on */ PSsetwaitcursorenabled(YES); /* * if the user didn't drop the window over an accepting window, or the * window didn't accept it, animate the transparent window back to its origin */ if (!accepted) { deltaX = currentPoint.x - startingPoint->x; deltaY = currentPoint.y - startingPoint->y; if (deltaX && deltaY) { distance = sqrt(deltaX * deltaX + deltaY * deltaY); frames = ceil(40.0 * distance / 5000.0); if (frames == 1) { /* make an exception for windows close to their origin */ frames = ceil(40.0 * distance / 1400.0); } increment.x = deltaX / frames; increment.y = deltaY / frames; /* we need to remember the mouse offset */ mouseOffset = *offset; [animator startEntry]; return self; } } /* destroy the windows and gstates used to drag the TransparentWindow */ cleanup(iWindow, bgWindow, niWindow, gWindow, igstate, bggstate, nigstate, ggstate); return [self free]; } - animateBack:sender { /* compute the transparent window's new location */ currentPoint.x -= increment.x; currentPoint.y -= increment.y; /* see if new location is close enough to the final position */ if ((increment.x > 0 && (currentPoint.x < stoppingPoint.x + 3.0)) || (increment.x < 0 && (currentPoint.x > stoppingPoint.x - 3.0))) { currentPoint.x = stoppingPoint.x; } if ((increment.y > 0 && (currentPoint.y < stoppingPoint.y + 3.0)) || (increment.y < 0 && (currentPoint.y > stoppingPoint.y + 3.0))) { currentPoint.y = stoppingPoint.y; } /* move it there */ miniDragWindow(iWindow, niWindow, gWindow, igstate, bggstate, nigstate, imageGstate, ggstate, currentPoint.x, currentPoint.y, mouseOffset.x, mouseOffset.y, windowSize.width, windowSize.height); /* count down the number of frames */ if (--frames) { return self; } /* all done */ [animator stopEntry]; cleanup(iWindow, bgWindow, niWindow, gWindow, igstate, bggstate, nigstate, ggstate); return [self free]; } - checkForAcceptWindow:(int)windowNumUnderMouse atPoint:(NXPoint *)point :(int *)windowUnderMouseChanged :(int *)previousWindowUnderMouseChanged { unsigned int windowNum; id windowUnderMouse = NOWINDOW; *windowUnderMouseChanged = 0; *previousWindowUnderMouseChanged = 0; /* find the window object under the mouse point */ if (windowNumUnderMouse) { NXConvertGlobalToWinNum(windowNumUnderMouse, &windowNum); windowUnderMouse = [NXApp findWindow:windowNum]; if (![windowUnderMouse respondsTo:@selector(windowEntered:fromSource:)]) { windowUnderMouse = NOWINDOW; windowNumUnderMouse = 0; } } /* * tell the window previously under the mouse (if different) that the image * exited */ if (windowUnderMouse != previousWindowUnderMouse && previousWindowUnderMouse != NOWINDOW) { if ([previousWindowUnderMouse windowExited:source]) { *previousWindowUnderMouseChanged = previousWindowNumUnderMouse; } } /* tell the window under the mouse (if it exists) that the image entered */ if (windowUnderMouse != NOWINDOW) { if ([windowUnderMouse windowEntered:point fromSource:source]) { *windowUnderMouseChanged = windowNumUnderMouse; } } previousWindowUnderMouse = windowUnderMouse; previousWindowNumUnderMouse = windowNumUnderMouse; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.