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.