This is FileShelfView.m in view mode; [Download] [Up]
#import "FileShelfView.h" #import "FileCollection.h" #import "TokenString.h" #import "FileName.h" static id font; @interface FileShelfView (PRIVATE) - _burstNames; - (const char *) _formatFileName: str width: (float)len; - (NXPoint *) _pointForIndex: (int) index; - (int) _indexForPoint: (NXPoint *)hit; @end @implementation FileShelfView -initFrame:(const NXRect *)rect { [super initFrame: rect]; [self registerForDraggedTypes:&NXFilenamePboardType count:1]; images = [[List alloc] init]; fileNames = [[List alloc] init]; singleNames = [[FileCollection alloc] init]; nameListDirty = NO; font = [Font systemFontOfSize: 0 matrix: NX_IDENTITYMATRIX]; [self setEnabled: YES]; [self setTitleWidth: 60]; [self setShowNames: YES]; return self; } - free { [self unregisterDraggedTypes]; [images freeObjects]; [images free]; [fileNames freeObjects]; [fileNames free]; [singleNames freeObjects]; [singleNames free]; return [super free]; } - empty { [images freeObjects]; [fileNames freeObjects]; [self display]; return self; } - drawSelf:(NXRect *)r :(int) count { NXPoint *point; int cnt, y; const char *label; /* Erase the whole view */ if(enabled) NXDrawGrayBezel(&bounds, &bounds); /* with bezel if enabled */ else { NXSetColor ([window backgroundColor]); NXRectFill (&bounds); return self; } PSsetgray(NX_BLACK); [font set]; for(y = 0, cnt = [images count]; y < cnt; y++) { [[images objectAt: y] composite: NX_SOVER toPoint: point = [self _pointForIndex: y]]; if(showNames) { label = [self _formatFileName: [fileNames objectAt: y] width: titleWidth - 4.0 ]; PSmoveto((point->x + 24.0) - ([font getWidthOf: label]/2.0) , point->y - [font pointSize]); PSshow(label); } } return self; } - fileNames { if(nameListDirty) /* if the list has changed we need to burst it before accessing */ [self _burstNames]; return singleNames; } - setEnabled: (BOOL)flag /* will it accept files? */ { if(flag == enabled) return self; enabled = flag; [self empty]; [self display]; return self; } - (BOOL) enabled { return enabled; } - addFile: (const char *)filename /* add file(s) manually */ { id file = [[StringStorage alloc] init: filename]; NXImage *image; image = [[Application workspace] getIconForFile: [file stringValue]]; if(!(image && enabled)) { [file free]; return nil; } [images addObject: image]; [fileNames addObject: file]; [self display]; nameListDirty = YES; return self; } - mouseDown: (NXEvent *)anEvent { NXEvent saveEvent; NXPoint offset, origin; Pasteboard *dragPasteboard; offset.x = offset.y = 0; saveEvent = *anEvent; /* find the hit icon and its origin */ origin = anEvent->location; [self convertPoint: &origin fromView: nil]; dragIndex = [self _indexForPoint: &origin]; /* create and load pasteboard - then start drag */ dragPasteboard = [Pasteboard newName: NXDragPboard]; [dragPasteboard declareTypes: &NXFilenamePboardType num:1 owner:self]; [dragPasteboard writeType: NXFilenamePboardType data: [[fileNames objectAt: dragIndex] stringValue] length: [[fileNames objectAt: dragIndex] strlen]]; [self dragImage: [images objectAt: dragIndex] at: [self _pointForIndex: dragIndex] offset: &offset event: &saveEvent pasteboard: dragPasteboard source: self slideBack: NO]; return [super mouseDown: anEvent]; } - setShowNames: (BOOL) flag /* Should the names appear on the shelf? */ { showNames = flag; return self; } -(BOOL) showNames { return showNames; } - setTitleWidth: (float) aWidth /* how wide is a shelf slot - min 50 */ { titleWidth = (aWidth > 50.0 ? aWidth : 50.0); return self; } - (float) titleWidth { return titleWidth; } @end @implementation FileShelfView (NXDraggingDestinationProtocol) - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender { if(enabled && ([sender draggingSourceOperationMask] & NX_DragOperationCopy)) return NX_DragOperationCopy; else return NX_DragOperationNone; } - draggingExited:(id <NXDraggingInfo>) sender { return self; } - (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender { return YES; } - (BOOL)performDragOperation:(id <NXDraggingInfo>)sender { return ([self draggingEntered: sender] == NX_DragOperationNone) ? NO : YES; } - concludeDragOperation:(id <NXDraggingInfo>)sender { Pasteboard *pboard = [sender draggingPasteboard]; char *files; int len; id aFile; [pboard readType:NXFilenamePboardType data: &files length: &len]; if(len) { [images addObject: [sender draggedImageCopy]]; aFile = [[StringStorage alloc] init: files]; [fileNames addObject:aFile]; [self display]; nameListDirty = YES; } return self; } @end @implementation FileShelfView (FSVNXDraggingSource) - (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { return NX_DragOperationCopy; } - draggedImage:(NXImage *)image endedAt:(NXPoint *)screenPoint deposited:(BOOL)didDeposit { if(!didDeposit) { [[images removeObjectAt: dragIndex] free]; [[fileNames removeObjectAt: dragIndex] free]; [self display]; nameListDirty = YES; } return self; } - (BOOL)ignoreModifierKeysWhileDragging { return NO; } @end @implementation FileShelfView (PRIVATE) /* * fileNames may contain multiple file entries - break them out to single entries. */ - _burstNames { int x, cnt; id someNames = [[TokenString alloc] init]; id aFileName; const char *fileNameStr; [singleNames freeObjects]; /* free old version of the list */ [someNames setSeparator: '\t']; for(x = 0, cnt = [fileNames count]; x < cnt; x++) { [someNames setStringValue: [[fileNames objectAt: x] stringValue]]; while(fileNameStr = [someNames popStringValue]) { aFileName = [[StringStorage alloc] init: fileNameStr]; [singleNames addObject: aFileName]; } } [someNames free]; nameListDirty = NO; return self; } - (const char *) _formatFileName: fn width: (float)len { /* format file names like the Workspace shelf. Handle multiple items */ static char buf[MAXPATHLEN]; const char *str = [fn stringValue]; int x, cnt; for(cnt = 0, x = 0; str[x]; x++) { if(str[x] == '\t') cnt++; } if(cnt) sprintf(buf,"%d items", cnt + 1); else strcpy(buf,[fn basename]); if([font getWidthOf: buf] > len) { for(x = strlen(str); x > 0 ; x--) { if([font getWidthOf: buf] <= len) break; buf[x - 1] = (char)0; } strcpy(buf + (x - 3), "..."); } return buf; } - (NXPoint *) _pointForIndex: (int) index /* calculate the corner point for the nth icon */ { static NXPoint point; int row, perRow; perRow = NX_WIDTH(&bounds)/titleWidth; row = (index/perRow) + 1; point.x = (float)((index % perRow) * titleWidth) + ((titleWidth/2.0) - 24.0); point.y = NX_HEIGHT(&bounds) - (row * 52); if(showNames) point.y -= ((row - 1) * [font pointSize]); return &point; } - (int) _indexForPoint: (NXPoint *)hit /* based on a point which icon was hit? */ { int column, row; row = (NX_HEIGHT(&bounds) - hit->y)/(52 + (showNames ? [font pointSize] : 0)); column = hit->x/titleWidth; return column + (row * (int)(NX_WIDTH(&bounds)/titleWidth)); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.