This is ShelfView.m in view mode; [Download] [Up]
#import "Fiend.h" #import "ShelfView.h" #import "IconView.h" #import "IconDragView.h" #import "ProgressView.h" #import "Controller.h" #import "compositeBackground.h" #import <math.h> #import <appkit/appkit.h> #import <3Dkit/3Dkit.h> #import <ansi/stdio.h> #import <ansi/string.h> @implementation ShelfView - initFrame:(const NXRect *) aFrame { int screenCount; char *backgroundString; NXScreen *screens; const char *fileString; const char *colorString; const char *const types[1] = {NXFilenamePboardType}; gridValue = atoi(NXGetDefaultValue([NXApp appName], SGRID_VALUE)); gridEnabled = !strcmp(NXGetDefaultValue([NXApp appName], GRID_ENABLE), "YES"); [super initFrame:aFrame]; [[self window] setDelegate:self]; [self registerForDraggedTypes:types count:1]; /* * Determine the background color. */ useBGColor = NO; [NXApp getScreens:&screens count:&screenCount]; if (screens[0].depth == NX_TwoBitGrayDepth) backgroundString = "BWBackgroundColor"; else backgroundString = "BackgroundColor"; colorString = NXGetDefaultValue("NeXT1", backgroundString); if (colorString) { float r, g, b; sscanf(colorString, "%f %f %f", &r, &g, &b ); bgColor = NXConvertRGBAToColor(r, g, b, NX_NOALPHA); useBGColor = YES; } /* * Now that we've set up our view's appearance, do the rest of the * initialization we need to do. */ [window disableFlushWindow]; [self readShelf:YES]; tileImage = !strcmp(NXGetDefaultValue([NXApp appName], TILE_IMAGE), "YES"); fileString = NXGetDefaultValue([NXApp appName], IMAGE_NAME); if (fileString) [self setImageFileName:fileString]; [[window reenableFlushWindow] flushWindow]; return self; } - free { if (theImage != nil) [theImage free]; return [super free]; } - (BOOL) acceptsFirstMouse { return YES; } - (NXColor) backgroundColor { if (useBGColor) return bgColor; else return NX_COLORLTGRAY; } - (BOOL) isAnyViewAt:(NXPoint) aPoint besides:aView { id testView; int i; NXRect rect; NXRect interRect; int max = [subviews count]; for (i = 0; i < max; i++) { if ((testView = [subviews objectAt:i]) == aView) continue; [testView getFrame:&rect]; NXSetRect(&interRect, aPoint.x, aPoint.y, gridValue, gridValue); if (NXIntersectionRect(&rect, &interRect)) return YES; } return NO; } /* * Align all of our IconViews on the grid. Take care so that none overlap. */ - (void) alignSubviews { int i; int max = [subviews count]; for (i = 0; i < max; i++) { id view = [[self subviews] objectAt:i]; NXRect rect; NXPoint candidatePt; int count; if (![view isKindOf:[IconView class]]) continue; /* * Make the icon the right size, and then compute the new origin. */ [view getFrame:&rect]; candidatePt.x = gridValue * (int)(rect.origin.x/gridValue); candidatePt.y = gridValue * (int)(rect.origin.y/gridValue); count = bounds.size.height * bounds.size.width / gridValue; while (count-- > 0 && [self isAnyViewAt:candidatePt besides:view]) { candidatePt.x -= gridValue; if (candidatePt.x < 0) { candidatePt.x = gridValue; candidatePt.y -= gridValue; if (candidatePt.y < gridValue) { candidatePt.y = gridValue; candidatePt.x -= gridValue; } } } [view moveTo:candidatePt.x :candidatePt.y]; } [self writeShelf]; [self display]; } - (BOOL)tileImage { return tileImage; } - setTileImage:(BOOL)flag { tileImage = flag; NXWriteDefault([NXApp appName], TILE_IMAGE, (flag)?"YES":"NO"); return self; } - (char *)getImageFileName { return imageFileName; } - setImageFileName:(const char *)theName { id image; id repList; int i; NXSize imageSize; NXImageRep *rep; if (!theName || !strlen(theName)) { theImage = nil; imageFileName[0] = '\0'; } else { image = [[NXImage alloc] initFromFile:theName]; if (image == nil) { NXBeep(); return nil; } [theImage free]; theImage = image; [theImage getSize:&imageSize]; if (!tileImage || NX_WIDTH(&frame) < imageSize.width || NX_HEIGHT(&frame) < imageSize.height) { [theImage setScalable:YES]; [theImage setSize:&frame.size]; } strcpy(imageFileName, theName); repList = [theImage representationList]; for(i = 0; i < [repList count]; i++) { rep = [repList objectAt:i]; if ([rep isKindOf:[N3DRIBImageRep class]]) { [(N3DRIBImageRep *)rep setSurfaceType:N3D_FacetedSolids]; break; } } } (void) NXWriteDefault([NXApp appName], IMAGE_NAME, imageFileName); [self display]; return self; } - (BOOL) gridEnabled { return gridEnabled; } - (void)setGridEnabled:(BOOL) flag { gridEnabled = flag; (void) NXWriteDefault([NXApp appName], GRID_ENABLE, flag ? "YES" : "NO"); } - (int)gridValue { return gridValue; } - setGridValue:(int)aValue { char gridString[20]; if (aValue == gridValue) return self; gridValue = aValue; if (gridValue < MIN_GRID_VALUE) gridValue = MIN_GRID_VALUE; else if (gridValue > MAX_GRID_VALUE) gridValue = MAX_GRID_VALUE; [window disableFlushWindow]; [[self subviews] freeObjects]; [IconView resetCachedShelfImages]; [[self readShelf:NO] display]; [[window reenableFlushWindow] flushWindow]; sprintf(gridString, "%d", gridValue); NXWriteDefault([NXApp appName], SGRID_VALUE, gridString); return self; } - drawSelf:(const NXRect *) rects :(int) rectCount { int i; int j; int rectIndex; int vertCount; int horizCount; NXPoint thePoint; NXRect interRect; NXRect theRect = {{0.0, 0.0}, {0.0, 0.0}}; if (useBGColor) { NXSetColor(bgColor); NXRectFill(rects); } else compositeFromWorkspaceWindow(rects->origin.x, rects->origin.y, rects->size.width, rects->size.height); if (theImage != nil) { [theImage getSize:&theRect.size]; vertCount = NX_HEIGHT(&frame)/NX_HEIGHT(&theRect); horizCount = NX_WIDTH(&frame)/NX_WIDTH(&theRect); for(rectIndex = 0; rectIndex < rectCount; rectIndex++) { for(i = 0; i < horizCount+1; i++) { for(j = 0; j < vertCount+1; j++) { NXSetRect(&interRect, NX_WIDTH(&theRect)*i, NX_HEIGHT(&theRect)*j, NX_WIDTH(&theRect), NX_HEIGHT(&theRect)); if (NXIntersectionRect(&rects[rectIndex], &interRect)) { thePoint = interRect.origin; NX_X(&interRect) = fmod(NX_X(&interRect), NX_WIDTH(&theRect)); NX_Y(&interRect) = fmod(NX_Y(&interRect), NX_HEIGHT(&theRect)); [theImage composite:NX_SOVER fromRect:&interRect toPoint:&thePoint]; } } } } } return self; } - deselectAll:sender { NXRect away = {{-100.0, -100.0}, {1.0, 1.0}}; [self selectViewsInRect:&away deselect:YES]; return NO; } - removeView:aView { NXRect viewFrame; [aView getFrame:&viewFrame]; [aView removeFromSuperview]; [self display:&viewFrame :1 :NO]; return self; } - addView:aView { NXRect viewFrame; [aView getFrame:&viewFrame]; [self addSubview:aView]; [self display:&viewFrame :1 :NO]; return self; } - deleteView:aView { [self removeView:aView]; [aView free]; return self; } /* * Return true if the point is in the area we use to get rid of views */ - (BOOL) isDeadZone:(NXPoint *) aPoint { NXRect goodZone = bounds; NXInsetRect(&goodZone, 2, 2); return !NXMouseInRect(aPoint, &goodZone, NO); } - (void) createViewForPath:(const char *) path at:(NXPoint *) point { id image; id newView; struct stat st; NXRect aRect = {{0.0, 0.0}, {gridValue, gridValue}}; if (stat(path, &st) < 0) return; image = [IconView getImageForPath:path fileIcon:NO]; newView = [[IconDragView alloc] initFrame:&aRect image:image data:path andLength:strlen(path)+1 useSize:YES onDock:NO]; aRect.origin = *point; [[newView setFrame:&aRect] display]; [self addSubview:newView]; [newView getFrame:&aRect]; [self display:&aRect :1 :NO]; } static BOOL prefix(const char *prefix, const char *string) { while (*prefix && *string && *prefix == *string) { prefix++; string++; } return *prefix == '\0'; } - (void) removeViewForPath:(const char *) fullPath { int i = [[self subviews] count]; while (i > 0) { char *path; unsigned int len; id view = [[self subviews] objectAt:i]; if ([view isKindOf:[IconView class]]) { [view getData:(void *) &path andLength:&len]; if (prefix(fullPath, path)) [self deleteView:view]; } i--; } } /* * Find the right position for the new image, based on the grid and the * mouse's location. */ - (NXPoint) viewLocationForContext:(id <NXDraggingInfo>)dragContext { NXPoint newLoc; NXPoint imagePt = [dragContext draggedImageLocation]; NXPoint mousePt = [dragContext draggingLocation]; NXPoint imageOffset; [draggedView getImagePoint:&imageOffset andHilitePoint:NULL]; if (gridEnabled) { NXRect rect; [draggedView getFrame:&rect]; newLoc.x = mousePt.x - ((int) mousePt.x % gridValue) + (gridValue - rect.size.width) / 2; newLoc.y = mousePt.y - (int) mousePt.y % gridValue; } else { newLoc.x = imagePt.x - imageOffset.x; newLoc.y = imagePt.y - imageOffset.y; } return newLoc; } /* * Make a ghost image to indicate that we're really a destination. */ - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender { NXSize aSize; NXPoint newLoc; if ([sender draggingSourceOperationMask] == NX_DragOperationNone) return NX_DragOperationNone; else if ([sender draggingSourceOperationMask] == NX_DragOperationPrivate) return NX_DragOperationNone; aSize.width = [self gridValue]; aSize.height = aSize.width; draggedView = [[IconView allocFromZone:[self zone]] initFromDragContext:sender andSize:&aSize onDock:NO]; newLoc = [self viewLocationForContext:sender]; [draggedView moveTo:newLoc.x :newLoc.y]; [draggedView setGhost:YES]; if (gridEnabled) [self addView:draggedView]; return NX_DragOperationLink; } /* * Move the dragged image, but only do it if we need to (that is, if the * mouse moved to a new grid cell). */ - (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender { NXPoint mouseLoc; NXPoint newLoc; NXRect aFrame; if ([sender draggingSourceOperationMask] == NX_DragOperationNone) return NX_DragOperationNone; newLoc = [self viewLocationForContext:sender]; if (!gridEnabled) return NX_DragOperationLink; /* * If the icon was dragged off the edge, hide it somewhere! */ mouseLoc = [sender draggingLocation]; if ([self isDeadZone:&mouseLoc]) { newLoc.x = -100; newLoc.y = -100; } if (gridEnabled) { [draggedView getFrame:&aFrame]; if (aFrame.origin.x != newLoc.x || aFrame.origin.y != newLoc.y) { [draggedView moveTo:newLoc.x :newLoc.y]; [self display:&aFrame :1 :NO]; /* erase old */ aFrame.origin = newLoc; [self display:&aFrame :1 :NO]; /* draw new */ } } return NX_DragOperationLink; } /* * Get rid of the resources we used to drag the image around. */ - draggingExited:(id <NXDraggingInfo>)sender { if ([sender draggingSourceOperationMask] == NX_DragOperationNone) return NX_DragOperationNone; if (gridEnabled) [self removeView:draggedView]; [draggedView free]; return self; } /* * Eat the result... */ - (BOOL) prepareForDragOperation:sender { return YES; } - (BOOL) performDragOperation:sender { NXPoint mouseLoc; NXPoint newLoc; /* * If the dragged item landed in the dead zone, get rid of it. * Don't accept drag. */ newLoc = [self viewLocationForContext:sender]; mouseLoc = [sender draggingLocation]; if ([self isDeadZone:&mouseLoc]) { [self removeView:draggedView]; [draggedView free]; draggedView = nil; return NO; } [draggedView moveTo:newLoc.x :newLoc.y]; return YES; } - selectViewsInRect:(NXRect *)theRect deselect:(BOOL)flag { id theView; int i; NXRect viewRect; NXPoint thePoint; int count = [subviews count]; BOOL found = NO; [window disableFlushWindow]; for(i = 0; i < count; i++) { theView = [subviews objectAt:i]; if (theView == nil) continue; [theView getFrame:&viewRect]; thePoint.x = NX_MIDX(&viewRect); thePoint.y = NX_MIDY(&viewRect); if (NXIntersectsRect(&viewRect, theRect)) { if (!flag) [theView setState:![theView state]]; else [theView setState:YES]; found = YES; } else if (flag) [theView setState:NO]; } [[window reenableFlushWindow] flushWindow]; if (found) [NXApp unhide:self]; return self; } - nukeViewsInRect:(NXRect *)theRect { id theView; int i; NXRect viewRect; NXPoint thePoint; int count = [subviews count]; id killList = [[List alloc] init]; BOOL useSound = !strcmp(NXGetDefaultValue([NXApp appName], USE_SOUND), "YES"); for(i = 0; i < count; i++) { theView = [subviews objectAt:i]; if (theView == nil) continue; [theView getFrame:&viewRect]; thePoint.x = NX_MIDX(&viewRect); thePoint.y = NX_MIDY(&viewRect); if (NXIntersectsRect(&viewRect, theRect)) [killList addObject:theView]; } count = [killList count]; for(i = 0; i < count; i++) [self deleteView:[killList objectAt:i]]; [killList free]; if (useSound) [[Sound findSoundFor:"Destroy"] play]; [self writeShelf]; return self; } - mouseDown:(NXEvent *)event { BOOL alt; BOOL ctrl; BOOL shift; BOOL command; NXRect theRect; NXPoint p; NXPoint origPt; BOOL started = NO; int mask = NX_MOUSEDRAGGEDMASK|NX_MOUSEUPMASK; alt = (event->flags & NX_ALTERNATEMASK) ? YES : NO; ctrl = (event->flags & NX_CONTROLMASK) ? YES : NO; shift = (event->flags & NX_SHIFTMASK) ? YES : NO; command = (event->flags & NX_COMMANDMASK) ? YES : NO; origPt = event->location; [window convertBaseToScreen:&origPt]; if (event->data.mouse.click == 2) { [NXApp unhide:self]; return self; } [window addToEventMask:NX_MOUSEDRAGGEDMASK]; do { if (!started) { [self lockFocus]; PSsetgray(NX_BLACK); PSsetinstance(YES); started = YES; } p = event->location; NX_X(&theRect) = (origPt.x < p.x) ? origPt.x : p.x; NX_Y(&theRect) = (origPt.y < p.y) ? origPt.y : p.y; NX_WIDTH(&theRect) = fabs(origPt.x - p.x); NX_HEIGHT(&theRect) = fabs(origPt.y - p.y); PSnewinstance(); NXFrameRect(&theRect); event = [NXApp getNextEvent:mask]; } while (event && event->type != NX_MOUSEUP); if (started) { PSnewinstance(); PSsetinstance(NO); [self unlockFocus]; PSsetgray(NX_BLACK); if (alt) [self nukeViewsInRect:&theRect]; else { [[NXApp delegate] deselectDock]; [self selectViewsInRect:&theRect deselect:!shift]; } } return self; } /* * Actually write the stuff way down here. It's completely at the end * of the operation, so a slow write won't hose the UI. */ - concludeDragOperation:(id <NXDraggingInfo>)sender { int len; int horizLimit; int horizCount; char *ptr; char *path; char *dragString; NXRect newFrame; NXRect viewFrame; NXPoint newPoint; BOOL useSound = !strcmp(NXGetDefaultValue([NXApp appName], USE_SOUND), "YES"); [draggedView getFrame:&viewFrame]; newFrame = viewFrame; newPoint = viewFrame.origin; [draggedView getData:(void **)&dragString andLength:&len]; horizCount = 0; horizLimit = 1000; if ([sender draggingSourceOperationMask] & NX_DragOperationLink) { horizLimit = 0; ptr = dragString; while(*ptr) { if (*ptr == '\t') horizLimit++; ptr++; } horizLimit = (int)sqrt((float)horizLimit); } path = strtok(dragString, "\t"); while(path && strlen(path)) { while([self isAnyViewAt:newPoint besides:draggedView]) { if (newPoint.x >= gridValue && horizCount < horizLimit) { newPoint.x -= gridValue; horizCount++; } else { horizCount = 0; newPoint.x = NX_X(&viewFrame); if (newPoint.y >= gridValue && newPoint.y <= NX_Y(&viewFrame)) newPoint.y -= gridValue; else if (newPoint.y >= gridValue) newPoint.y += gridValue; else newPoint.y = NX_Y(&viewFrame) + gridValue; } } newFrame.origin = newPoint; [self createViewForPath:path at:&newFrame.origin]; NXPing(); path = strtok(NULL, "\t"); } if (useSound && ![sender isDraggingSourceLocal]) [[Sound findSoundFor:"Fiend"] play]; if (draggedView != nil) { [self removeView:draggedView]; [draggedView free]; } [self writeShelf]; return self; } /* * Be a drag source, too */ - setDragView:aView onEvent:(NXEvent *) e withOffset:(NXPoint *) offset atLocation:(const NXPoint *) location { id pb = [Pasteboard newName:NXDragPboard]; void *data; unsigned int length; NXPoint myLoc; /* * Initiate a drag operation. Copy stuff into the pasteboard, * then start dragging. To simplify matters elsewhere, we try * to make a local dragging operation look just like a non-local * one. */ dragSourceView = aView; keepSourceOnShelf = (e->flags & NX_SHIFTMASK) ? YES : NO; [aView getData:&data andLength:&length]; [pb declareTypes:&NXFilenamePboardType num:1 owner:nil]; [pb writeType:NXFilenamePboardType data:data length:length]; myLoc = *location; [aView convertPoint:&myLoc toView:self]; [self dragImage:[aView image] at:&myLoc offset:offset event:e pasteboard:pb source:self slideBack:YES]; return self; } - draggedImage:(NXImage *)image beganAt:(NXPoint *)screenPoint { NXRect theFrame; [dragSourceView getFrame:&theFrame]; [self display:&theFrame :1 :NO]; if (!keepSourceOnShelf) [self removeView:dragSourceView]; return self; } /* * A drag operation, with us as the source, finished. If it was an * unsuccessful drag then, put the source back! If it was a successful * drag, and we weren't the destination, then remove the thing from the * shelf. */ - draggedImage:(NXImage *)image endedAt:(NXPoint *)screenPoint deposited:(BOOL)didDeposit { char *path; unsigned int len; struct stat st; /* * Check to see if we should keep the source dir on the shelf. We * do this if the keepSourceOnShelf flag is set, and if the file * under the icon still exists. */ [dragSourceView getData:(void **) &path andLength:&len]; if (keepSourceOnShelf && path && stat(path, &st) == 0) { keepSourceOnShelf = NO; return self; } /* * The source isn't on the screen, so either get rid of the source, or * put it back. */ if (didDeposit) [self deleteView:dragSourceView]; else [self addView:dragSourceView]; return self; } - (NXDragOperation) draggingSourceOperationMaskForLocal:(BOOL)flag { return NX_DragOperationAll; } - (BOOL)hasSelectedCells { int i; int count = [subviews count]; for(i = 0; i < count; i++) { if ([[subviews objectAt:i] state]) return YES; } return NO; } - copy:sender andCut:(BOOL)cutFlag { id aView; int i; int junk; char *viewPath; char cutString[10000]; int count = [subviews count]; id pb = [Pasteboard newName:NXGeneralPboard]; id cutList = [[List alloc] init]; const char *types[] = {NXFilenamePboardType, NXAsciiPboardType}; BOOL useSound = !strcmp(NXGetDefaultValue([NXApp appName], USE_SOUND), "YES"); *cutString = '\0'; for(i = 0; i < count; i++) { aView = [subviews objectAt:i]; if ([aView state]) { [aView getData:(void **)&viewPath andLength:&junk]; strcat(cutString, viewPath); strcat(cutString, "\t"); [cutList addObject:aView]; } } cutString[strlen(cutString)-1] = '\0'; [pb declareTypes:types num:2 owner:nil]; [pb writeType:NXFilenamePboardType data:cutString length:strlen(cutString)]; for(i = 0; i < strlen(cutString); i++) { if (cutString[i] == '\t') cutString[i] = '\n'; } strcat(cutString, "\n"); [pb writeType:NXAsciiPboardType data:cutString length:strlen(cutString)]; if (cutFlag) { if (useSound) [[Sound findSoundFor:"Destroy"] play]; count = [cutList count]; for(i = 0; i < count; i++) [self deleteView:[cutList objectAt:i]]; } [cutList free]; [self writeShelf]; return self; } - paste:sender { int len; int horizLimit; int horizCount; char *ptr; char *path; char *dragString; BOOL ctrl; NXRect newFrame; NXEvent *event; NXPoint newPoint; NXPoint locus; id pb = [Pasteboard newName:NXGeneralPboard]; NXRect viewFrame = {{0.0, 0.0}, {gridValue, gridValue}}; BOOL useSound = !strcmp(NXGetDefaultValue([NXApp appName], USE_SOUND), "YES"); [pb readType:NXFilenamePboardType data:&dragString length:&len]; if (!len) return self; [NXIBeam push]; do { event = [NXApp getNextEvent:NX_MOUSEDOWNMASK|NX_MOUSEDRAGGEDMASK]; } while (event && event->type != NX_MOUSEDOWN); ctrl = (event->flags & NX_CONTROLMASK) ? YES : NO; [NXIBeam pop]; locus = event->location; locus.x = locus.x - (int)locus.x % gridValue; locus.y = locus.y - (int)locus.y % gridValue; newPoint = locus; viewFrame.origin = locus; newFrame = viewFrame; horizCount = 0; horizLimit = 10000; if (len && !ctrl) { horizLimit = 0; ptr = dragString; while(*ptr) { if (*ptr == '\t') horizLimit++; ptr++; } horizLimit = (int)sqrt((float)horizLimit); } [window disableFlushWindow]; path = strtok(dragString, "\t"); while(path && strlen(path)) { while([self isAnyViewAt:newPoint besides:nil]) { if (newPoint.x >= gridValue && horizCount < horizLimit) { newPoint.x -= gridValue; horizCount++; } else { horizCount = 0; newPoint.x = NX_X(&viewFrame); if (newPoint.y >= gridValue && newPoint.y <= NX_Y(&viewFrame)) newPoint.y -= gridValue; else if (newPoint.y >= gridValue) newPoint.y += gridValue; else newPoint.y = NX_Y(&viewFrame) + gridValue; } } newFrame.origin = newPoint; [self createViewForPath:path at:&newFrame.origin]; NXPing(); path = strtok(NULL, "\t"); } [[window reenableFlushWindow] flushWindow]; if (useSound) [[Sound findSoundFor:"Fiend"] play]; [pb deallocatePasteboardData:dragString length:len]; return self; } /* * Open the shelf file. */ - (FILE *) openShelfFor:(char *) how { char path[MAXPATHLEN]; sprintf(path, "%s/%s", NXHomeDirectory(), FIENDSHELF_FILE); return fopen(path, how); } /* * Close it. */ - closeShelf:(FILE *) file { fclose(file); return self; } /* * Read the contents of the shelf in from a file. The file's format consists * of lines of the form: * * x y path * * where the two numbers x,y specify the origin of the particular view on the * shelf, and path specifies the path to the workspace. Somewhat bogusly, * we assume the path starts at character 14. */ - readShelf:(BOOL)showProgress { float i; float count; FILE *file; char line[MAXPATHLEN + 30]; char *path; NXPoint point; file = [self openShelfFor:"r"]; if (file == NULL) return self; count = 0.0; if (showProgress) { while(fgets(line, sizeof(line), file)) count++; rewind(file); [[NXApp delegate] setProgressViewRatio:0.0]; } i = 1.0; while (fgets(line, sizeof(line), file)) { if (showProgress) [[NXApp delegate] setProgressViewRatio:0.9*i++/count]; /* * Parse the line in the shelf. It's too bad that we can't use * sscanf to parse the whole line! */ sscanf(line, "%f %f", &point.x, &point.y); /* file string starts after second number, char 14 */ if (strlen(line) > 14) { path = line + 14; if (rindex(path, '\n') != NULL) *rindex(path, '\n') = '\0'; } else continue; /* * Make a spot for this guy... */ [self createViewForPath:path at:&point]; } [self closeShelf:file]; return self; } /* * Write the contents of the shelf out to the shelf file. */ - writeShelf { FILE *file; NXRect rect; int i; file = [self openShelfFor:"w"]; if (file == NULL) return self; for (i = 0; i < [[self subviews] count]; i++) { id view = [[self subviews] objectAt:i]; unsigned int length; char *path; if (![view isKindOf:[IconView class]] || [view isOnRemovableMedia]) continue; [view getData:(void **) &path andLength:&length]; [view getFrame:&rect]; fprintf(file, "%6.0f %6.0f %s\n", rect.origin.x, rect.origin.y, path); } [self closeShelf:file]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.