This is IKSuitcase.m in view mode; [Download] [Up]
/* File IKSuitcase.m Release 1.2, 7 June 1994 Copyright (C) 1994 by H. Scott Roy This code is part of IconKit, a general toolbox for drag-and-drop applications. IconKit is free for noncommercial use, but costs money for a commercial license. You should have received a copy of the license agreement with this file. If not, a copy of the license and the complete source of IconKit can be obtained from the author: H. Scott Roy 2573 Stowe Ct. Northbrook, IL 60062-8103 iconkit@cs.stanford.edu For your editing convenience, this file is best viewed using an editor that automatically wraps long lines, in a fixed point font at 80 columns, with tabs every 4 spaces. */ /* ========================================================================== */ /* An IKSuitcase defines the behavior of suitcases in ProjectBuilder and folders in the workspace. It displays itself as a suitcase and acts as a dragging destination. Since it inherits from IKList, IKSuitcase conforms to the IKDependency protocol and sends out messages to its users. */ #import <appkit/appkit.h> #import <objc/objc-runtime.h> #import "iconkit.h" @implementation IKSuitcase /* ========================================================================== */ /* IKSuitcase objects are all given the same default suitcase icons. These can be changed with appropriate messages. */ static NXImage * suitcase; static NXImage * openSuitcase; + initialize { if (self == [IKSuitcase class]) { IKInitIDpboardType(); suitcase = [NXImage findImageNamed: "Suitcase"]; openSuitcase = [NXImage findImageNamed: "OpenSuitcase"]; } return self; } - (NXImage *) getIBImage { return suitcase; } - (const char *) getInspectorClassName { return "IKSuitcaseInspector"; } /* ========================================================================== */ /* An IKSuitcase keeps track of its own name and images. You should make an extra copy of any images you don't want to go away when the IKSuitcase is freed. */ - init { return [self init: "IconKit"]; } - init: (const char *) theName count: (unsigned) n { if ((self = [super initCount: n]) != nil) { name = NXCopyStringBuffer(theName); image = nil; acceptingDragImage = nil; dragging = nil; draggingSession = -1; [self setClassToHold: ""]; } return self; } - init: (const char *) theName { return [self init: theName count: 0]; } - initCount: (unsigned) n { return [self init: "" count: n]; } - copyFromZone: (NXZone *) zone { IKSuitcase * copy = [super copyFromZone: zone]; if (copy) { copy->name = NXCopyStringBufferFromZone(name, zone); copy->image = image; copy->acceptingDragImage = acceptingDragImage; copy->classToHold = classToHold ? NXCopyStringBuffer(classToHold) : NULL; } return copy; } - free { [users announce: @selector(willFree:)]; [[[users usersAndListeners] empty] addObject: self]; if (name) free(name); if (image && ![image name]) [image free]; if (acceptingDragImage && ![acceptingDragImage name]) [acceptingDragImage free]; image = acceptingDragImage = nil; name = NULL; users = [users free]; return self = [super free]; } /* ========================================================================== */ /* Here are the archiving methods. Archiving saves the images used by the suitcase, as well as the contents, but not the users. */ - read: (NXTypedStream *) stream { [super read: stream]; NXReadTypes (stream, "**", &name, &classToHold); image = NXReadObject (stream); acceptingDragImage = NXReadObject (stream); users = [[IKAnnouncer alloc] initOwner: self]; return self; } - write: (NXTypedStream *) stream { [super write: stream]; NXWriteTypes (stream, "**", &name, &classToHold); NXWriteObject (stream, image); NXWriteObject (stream, acceptingDragImage); return self; } /* ========================================================================== */ /* Here are the methods that control how an IKSuitcase is displayed in an IKCell. Setting an image returns the old image, so that it can be freed if needed. */ - image { return image ? image : suitcase; } - acceptingDragImage { return acceptingDragImage ? acceptingDragImage : openSuitcase; } - (const char *) name { return name; } - (BOOL) isEditable { return YES; } - (BOOL) isDraggable { return YES; } - (BOOL) isDragAccepting { return YES; } - (const char *) classToHold { return classToHold; } - setEditable: (BOOL) flag { return self; } - setDragAccepting: (BOOL) flag { return self; } - setName: (const char *) theName { if (name != NULL) free(name); name = theName ? NXCopyStringBuffer(theName) : NULL; [users announce: @selector(didChangeName:)]; return self; } - setImage: theImage { id old = image; image = theImage; [users announce: @selector(didChangeImage:)]; return old; } - setAcceptingDragImage: theImage { id old = acceptingDragImage; acceptingDragImage = theImage; [users announce: @selector(didChangeAcceptingDragImage:)]; return old; } - setClassToHold: (const char *) class { if (classToHold) free(classToHold); classToHold = class ? NXCopyStringBuffer(class) : NULL; return self; } /* ========================================================================== */ /* An IKSuitcase will accept dragged objects of kind classToHold with the approval of its users. The users are notified after any objects have been added so they can take appropriate action. */ - (NXDragOperation) draggingEntered: (id <NXDraggingInfo>) sender { int n = [sender draggingSequenceNumber]; id class; if (draggingSession != n) { draggingSession = n; class = classToHold ? objc_lookUpClass(classToHold) : nil; dragging = classToHold == NULL ? NULL: [class respondsTo: @selector(readFromPasteboard:)] ? [class readFromPasteboard: [sender draggingPasteboard]]: IKReadID ([sender draggingPasteboard]); } return op = (dragging && (dragging != self) && [users poll: @selector(list:willAdd:) with: dragging]) ? NX_DragOperationAll: NX_DragOperationNone; } - (BOOL) performDragOperation: (id <NXDraggingInfo>) sender { return ([self addObject: dragging] != nil); } /* ========================================================================== */ /* The rest of the dragging methods don't do anything, but we need to implement them so that they don't inadvertently get passed to the first object in the list. One of the hidden dangers of using forward:: that I didn't expect! */ - (NXDragOperation) draggingUpdated: (id <NXDraggingInfo>) sender { return op; } - draggingExited: (id <NXDraggingInfo>) sender { return nil; } - (BOOL) prepareforDragOperation: (id <NXDraggingInfo>) sender { return YES; } - concludeDragOperation: (id <NXDraggingInfo>) sender { return nil; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.