This is IconDragView.m in view mode; [Download] [Up]
#import "Fiend.h" #import "Dock.h" #import "IconDragView.h" #import "ShelfView.h" #import "DockMgrView.h" #import "Controller.h" #import "FiendWraps.h" #import <appkit/appkit.h> #import <mach/mach.h> #import <bsd/sys/file.h> int mouseMoved(NXPoint *o, int n, int mask); typedef enum { Unknown, SameDeviceOperation, WriteNotAllowed, CrossDeviceOperation, ApplicationDirectory } DragStatus; @interface Application(DavesMethod) - (int)contextNum; @end @implementation Application(DavesMethod) - (int)contextNum { return contextNum; } @end @implementation IconDragView : IconView - initFrame:(const NXRect *) newFrame image:anImage data:(const void *) someData andLength:(unsigned int) newLength useSize:(BOOL)sizeValid onDock:(BOOL)dockFlag { const char *const types[1] = {NXFilenamePboardType}; [self registerForDraggedTypes:types count:1]; [super initFrame:newFrame image:anImage data:someData andLength:newLength useSize:sizeValid onDock:dockFlag]; altImage = nil; selected = NO; dockDrag = NO; hideIcons = !strcmp(NXGetDefaultValue([NXApp appName], HIDE_ICONS), "YES"); return self; } - free { [altImage free]; return [super free]; } - sizeTo:(NXCoord) width :(NXCoord) height { NXSize aSize; [super sizeTo:width :height]; if (altImage) { [image getSize:&aSize]; [altImage setSize:&aSize]; } return self; } - drawSelf:(const NXRect *) rects :(int) rectCount { id tempImage = image; if (altImage) image = altImage; [super drawSelf:rects :rectCount]; image = tempImage; return self; } - image { return image; } - getData:(void **) aPtr andLength:(unsigned int *) aLength { *aPtr = data; *aLength = length; return self; } - handleMouseMoved:(NXEvent *)saveEvent imagePt:(NXPoint *)imgPt offsetPt:(NXPoint *)offPt { NXPoint imageLoc; NXImage *dragImage; NXPoint mousePoint = saveEvent->location; Pasteboard *pboard = [Pasteboard newName:NXDragPboard]; if (onDock) [[NXApp delegate] deselectShelf]; else [[NXApp delegate] deselectDock]; if (!onDock) { [superview setDragView:self onEvent:saveEvent withOffset:offPt atLocation:imgPt]; } else { dragImage = [[NXImage alloc] initSize:&frame.size]; [pboard declareTypes:&NXFilenamePboardType num:1 owner:nil]; [pboard writeType:NXFilenamePboardType data:data length:strlen(data)]; [self getImagePoint:&imageLoc andHilitePoint:NULL]; [dragImage lockFocus]; PScomposite(0.0, 0.0, NX_WIDTH(&frame), NX_HEIGHT(&frame), [window gState], 0.0, 0.0, NX_COPY); [dragImage unlockFocus]; [dockMgrView setDragView:self andOffset:&mousePoint]; [[self setGhost:YES] display]; NXPing(); dockDrag = YES; [self dragImage:dragImage at:&frame.origin offset:offPt event:saveEvent pasteboard:pboard source:dockMgrView slideBack:NO]; dockDrag = NO; [[self setGhost:NO] display]; NXPing(); [dragImage free]; } return self; } - (BOOL)handleSingleClick:(NXEvent *)e { NXPoint imageLoc; NXPoint upperRight; BOOL alt = (e->flags & NX_ALTERNATEMASK) ? YES : NO; BOOL shift = (e->flags & NX_SHIFTMASK) ? YES : NO; BOOL control = (e->flags & NX_CONTROLMASK) ? YES : NO; BOOL command = (e->flags & NX_COMMANDMASK) ? YES : NO; BOOL delivered = NO; const char *path = (const char *)data; if (onDock) [[NXApp delegate] deselectShelf]; else [[NXApp delegate] deselectDock]; if (!command && !shift && !alt && !control) { [self getImagePoint:&imageLoc andHilitePoint:NULL]; [self convertPoint:&imageLoc toView:nil]; [window convertBaseToScreen:&imageLoc]; upperRight.x = screenSize.width - 32; upperRight.y = screenSize.height - 32; if (onDock) [[dockMgrView currentDock] select:NO all:self]; else [superview deselectAll:self]; [self setState:YES]; [[Application workspace] slideImage:image from:&imageLoc to:&upperRight]; delivered = [[Application workspace] selectFile:path inFileViewerRootedAt:""]; [self setState:NO]; } else if (alt && !onDock) { [superview perform:@selector(deleteView:) with:self afterDelay:0.0 cancelPrevious:YES]; [superview perform:@selector(writeShelf) with:nil afterDelay:0.0 cancelPrevious:YES]; delivered = YES; } else if (control && onDock && isApp) { autoLaunch = !autoLaunch; [self display]; delivered = YES; } else if (alt && onDock) { [dockMgrView perform:@selector(deleteView:) with:self afterDelay:0.0 cancelPrevious:YES]; delivered = YES; } else if (shift) { [NXApp unhide:self]; [self setState:!selected]; delivered = YES; } else { if (onDock) [[dockMgrView currentDock] select:NO all:self]; else [superview deselectAll:self]; delivered = YES; } return delivered; } - hideSomeApps { PSWHideOtherApps(); return self; } - (BOOL)handleDoubleClick:(NXEvent *)e { NXPoint imageLoc; NXPoint upperRight; BOOL delivered = NO; BOOL alt = (e->flags & NX_ALTERNATEMASK) ? YES : NO; BOOL cmd = (e->flags & NX_COMMANDMASK) ? YES : NO; const char *path = (const char *)data; if (!isApp) { [self getImagePoint:&imageLoc andHilitePoint:NULL]; [self convertPoint:&imageLoc toView:nil]; [window convertBaseToScreen:&imageLoc]; upperRight.x = screenSize.width - 32; upperRight.y = screenSize.height - 32; [[Application workspace] slideImage:image from:&imageLoc to:&upperRight]; delivered = [[Application workspace] openFile:path]; } else if (cmd && isLaunched) { [self perform:@selector(hideSomeApps) with:nil afterDelay:1.0 cancelPrevious:YES]; delivered = [[Application workspace] launchApplication:path]; } else if (!alt) { if (!isLaunched) { [self setGhost:YES]; [self display]; NXPing(); isLaunched = [[Application workspace] launchApplication:path showTile:(!onDock || !hideIcons) autolaunch:NO]; } delivered = [[Application workspace] launchApplication:path]; } else if (!onDock && alt) delivered = [[Application workspace] openFile:path]; return delivered; } - mouseDown:(NXEvent *) e { int savedMask; NXPoint mousePoint; NXPoint offset; NXEvent newEvent; NXEvent savedEvent; BOOL delivered = NO; int mask = NX_LMOUSEDRAGGEDMASK|NX_LMOUSEUPMASK; savedEvent = *e; mousePoint = e->location; savedMask = [window addToEventMask:mask]; if (mouseMoved(&mousePoint, 2, mask)) { offset.x = mousePoint.x - e->location.x; offset.y = mousePoint.y - e->location.y; [self handleMouseMoved:&savedEvent imagePt:&imagePoint offsetPt:&offset]; } else { if (![NXApp peekNextEvent:NX_LMOUSEDOWNMASK into:&newEvent waitFor:0.2 threshold:NX_MODALRESPTHRESHOLD]) { delivered = [self handleSingleClick:&savedEvent]; } else { (void)[NXApp getNextEvent:NX_LMOUSEDOWNMASK]; delivered = [self handleDoubleClick:&savedEvent]; } if (!delivered) NXBeep(); } [window setEventMask:savedMask]; return self; } - (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { return NX_DragOperationAll; } - (BOOL) acceptsFirstMouse { return YES; } - (BOOL) acceptsFirstResponder { return NO; } #define OPEN_DIR_ICON_FILE ".opendir.tiff" #define DEFAULT_OPEN_DIR_FILE "/usr/lib/NextStep/Workspace.app/WM.app/openFolder.tiff" #define OPEN_HIGHLIGHT "OpenHighlight.tiff" - getOpenImageForDirectory:(const char *) dirname { struct stat st; char buf[MAXPATHLEN]; id newImage = nil; /* * See if there's a .opendir.tiff */ strncpy(buf, dirname, sizeof(buf)); strncat(buf, "/", sizeof(buf)); strncat(buf, OPEN_DIR_ICON_FILE, sizeof(buf)); if (access(buf, R_OK) == 0) { newImage = [[NXImage allocFromZone:[self zone]] initFromFile:buf]; if (newImage) return newImage; } /* * Before we use the default image, see if this thing is the * root of a mounted file system, and use the appropriate icon * if it is. */ if (stat(dirname, &st) >= 0 && st.st_ino == 2) { NXSize size; [image getSize:&size]; newImage = [[NXImage allocFromZone:[self zone]] initSize:&size]; if ([newImage lockFocus]) { NXPoint zeroPoint = {0,0}; id highlight = [NXImage allocFromZone:[self zone]]; char buf[MAXPATHLEN]; NXBundle *bundle; bundle = [NXBundle bundleForClass:[self class]]; if ([bundle getPath:buf forResource:OPEN_HIGHLIGHT ofType:"tiff"]) { [highlight initFromFile:buf]; [image composite:NX_SOVER toPoint:&zeroPoint]; [highlight composite:NX_SOVER toPoint:&zeroPoint]; [newImage unlockFocus]; return newImage; } } } if (access(DEFAULT_OPEN_DIR_FILE, R_OK) == 0) newImage = [[NXImage allocFromZone:[self zone]] initFromFile:DEFAULT_OPEN_DIR_FILE]; if (newImage != nil) return newImage; else return image; } /* * Figure out the various parameters of the drag. */ - (DragStatus) dragStatusForPath:(char *)dragPath { char *destinationPath; unsigned int junk; struct stat st; [self getData:(void **) &destinationPath andLength:&junk]; if (!strcmp(destinationPath, dragPath)) return WriteNotAllowed; if (!strcmp(&destinationPath[strlen(destinationPath)-4], ".app")) { dragDestType = NXApplicationFileType; return ApplicationDirectory; } /* * See if we should be a dragging destination. We need some way to * make this extendible. One way would be to associate a remote * object with the node, and ask it what it means to drag the * incoming object over the one on the screen... * * For now, interpret the data as a string. Stat it to see if it's * a directory, and if it is, say yes subject to access constraints. */ if (stat(destinationPath, &st) < 0 || (st.st_mode & S_IFMT) != S_IFDIR) return WriteNotAllowed; if (access(destinationPath, W_OK|X_OK) < 0) return WriteNotAllowed; /* * Cool! We're a directory. Check the directory from which we're * dragging, and see it's the same as this one, or if it's contained * in this one. */ dragDestType = NXDirectoryFileType; if (stat(destinationPath, &st) < 0) return Unknown; else { dev_t destDev = st.st_dev; ino_t destIno = st.st_ino; if (lstat(dragPath, &st) >= 0 && st.st_dev == destDev && destIno == st.st_ino) return WriteNotAllowed; } /* * Handle the case where the dragging destination and the dragging * source are on different file systems. In this case, we want to * copy by default, not move. */ if (stat(destinationPath, &st) >= 0) { dev_t destinationDevice = st.st_dev; if (lstat(dragPath, &st) >= 0) if (st.st_dev != destinationDevice) return CrossDeviceOperation; else return SameDeviceOperation; } return Unknown; } /* * Figure out what the drag operation should be for dragging a view onto * another view. */ - (NXDragOperation) dragOperationForContext:(id <NXDraggingInfo>) dragInfo { unsigned int junk; char *dragPath; char *nextPath; BOOL first = YES; NXDragOperation op = NX_DragOperationNone; id pb = [Pasteboard newName:NXDragPboard]; NXDragOperation maskOp = [dragInfo draggingSourceOperationMask]; [pb readType:NXFilenamePboardType data:&dragPath length:&junk]; /* * We might have been asked to drag multiple files. Loop over all of * them to see if they all have the same drag op. Fail if they don't! */ nextPath = dragPath; do { char path[MAXPATHLEN]; NXDragOperation thisOp = maskOp; strncpy(path, nextPath, MAXPATHLEN); if (index(path, '\t')) *index(path, '\t') = '\0'; switch ([self dragStatusForPath:path]) { case WriteNotAllowed: case Unknown: thisOp = NX_DragOperationNone; break; case ApplicationDirectory: if (maskOp == NX_DragOperationGeneric) thisOp = NX_DragOperationGeneric; else thisOp = NX_DragOperationNone; break; case CrossDeviceOperation: if (maskOp & NX_DragOperationCopy) { thisOp = NX_DragOperationCopy; break; } /* fall through */ case SameDeviceOperation: if (maskOp & NX_DragOperationGeneric) { thisOp = NX_DragOperationGeneric; break; } /* fall through */ default: break; } /* * Bail out of this operation isn't the same as the last one! */ if (first) { op = thisOp; first = NO; } else { if (op != thisOp) return NX_DragOperationNone; } /* * Advance to next file */ nextPath = index(nextPath, '\t'); if (nextPath == NULL) break; else nextPath++; } while (1); return op; } /* * Be a dragging destination... */ - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender { lastDragOp = [self dragOperationForContext:sender]; if (lastDragOp == NX_DragOperationPrivate || lastDragOp == NX_DragOperationNone) return NX_DragOperationNone; else if (dragDestType == NXDirectoryFileType) { NXSize imageSize; altImage = [self getOpenImageForDirectory:data]; [image getSize:&imageSize]; [altImage setScalable:YES]; [altImage setSize:&imageSize]; [self display]; } return lastDragOp; } - (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender { lastDragOp = [self dragOperationForContext:sender]; return lastDragOp; } - draggingExited:(id <NXDraggingInfo>)sender { /* * Reset image to original image. */ [altImage free]; altImage = nil; [self display]; [window flushWindow]; return self; } /* * Eat the result... */ - (BOOL) prepareForDragOperation:sender { return YES; } - (BOOL) performDragOperation:(id <NXDraggingInfo>)sender { return YES; } - concludeDragOperation:(id <NXDraggingInfo>)sender { char *path; char *pbData; char *dragPath; const char *wsmOp; unsigned int pbLength; id workspace = [Application workspace]; id pb = [Pasteboard newName:NXDragPboard]; [pb readType:NXFilenamePboardType data:&pbData length:&pbLength]; dragPath = malloc(pbLength); bcopy(pbData, dragPath, pbLength); if (dragDestType == NXDirectoryFileType) { switch (lastDragOp) { case NX_DragOperationGeneric: wsmOp = WSM_MOVE_OPERATION; break; case NX_DragOperationLink: wsmOp = WSM_LINK_OPERATION; break; case NX_DragOperationCopy: wsmOp = WSM_COPY_OPERATION; break; default: return NO; } [workspace performFileOperation:wsmOp source:"/" destination:data files:pbData options:NULL]; } else if (dragDestType == NXApplicationFileType && lastDragOp == NX_DragOperationGeneric) { if (!isLaunched) { [[self setGhost:YES] display]; NXPing(); [workspace launchApplication:data showTile:(!onDock || !hideIcons) autolaunch:NO]; } path = strtok(dragPath, "\t"); while(path && strlen(path)) { [workspace openFile:path withApplication:data andDeactivate:YES]; path = strtok(NULL, "\t"); } } return [self draggingExited:sender]; } - (BOOL) isOnRemovableMedia { struct stat st; char *mountedList = NULL; id workspace = [Application workspace]; if (stat(data, &st) < 0) device = 0; else device = st.st_dev; removable = NO; if ([workspace respondsTo:@selector(getMountedRemovableMedia:)] && [workspace getMountedRemovableMedia:&mountedList]) [self perform:@selector(isOnRemovableDevice:) withPaths:mountedList]; if (mountedList) free(mountedList); return removable; } - isOnRemovableDevice:(const char *)path { struct stat st; if (path && stat(path, &st) >= 0) removable |= (device == st.st_dev); return self; } @end /* * Returns true if mouse is dragged more than n pixels from 'o', * false if the mouse button is lifted. If the mouse button is * lifted, the mouseUp event is not consumed. */ int mouseMoved(NXPoint *o, int n, int mask) { NXEvent e; NXPoint p; float dx, dy; do { [NXApp peekNextEvent:mask into:&e waitFor:0x7fffffff threshold:NX_MODALRESPTHRESHOLD]; p = e.location; if (e.type == NX_LMOUSEUP) break; (void) [NXApp getNextEvent:mask]; /* throw it away */ dx = abs(p.x - o->x); dy = abs(p.y - o->y); } while ((dy < (float) n) && (dx < (float) n)); *o = p; return e.type != NX_LMOUSEUP; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.