home *** CD-ROM | disk | FTP | other *** search
- // 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