This is CustomMenu.m in view mode; [Download] [Up]
// Written by Gideon King // // Source file : CustomMenu.m // Created by : gideon@berd // Created on : Fri Sep 8 16:26:38 NZST 1995 // RCS File : $Source: /Ramoth/Black.Albatross/CVS/CustomMenu/CustomMenu.subproj/CustomMenu.m,v $ // Last modified : $Date: 1995/09/10 22:38:07 $ // Last modified by : $Author: gideon $ // Current Revision : $Revision: 1.1.1.1 $ // static const char RCSId[] = "$Id: CustomMenu.m,v 1.1.1.1 1995/09/10 22:38:07 gideon Exp $"; // This class is set up to be the destination of the drag operation. It creates new menu items as required, // and deletes unwanted items when you Control-click on the item. I tried all sorts of strategies to remove // submenus, and didn't sort it out. What I therefore do is remove the item from the submenu and close myself, // so you can't get at me again. This means that you can't access the menu again, and it is not saved to the // menu list file, so it only takes up a bit of memory until you restart the app. Not very nice, and I'd like // to sort it out. Any suggestions??? #import "CustomMenu.h" @implementation CustomMenu - (const char *)version { return RCSId; } - myInit { const char *const types[] = {MHMenuCellPboardType}; // Register which pasteboard we you will accept [self registerForDraggedTypes:(const char *const*)&types count:1]; return self; } // Normal menu initialisers - init { [super init]; [self myInit]; return self; } - initTitle:(const char *)aTitle { [super initTitle:aTitle]; [self myInit]; return self; } // Used in this case for removing menu items when a Control key is down - mouseDown:(NXEvent *)theEvent { // Only remove the item from the menu a Control key is down // This is not really a very destructive operation, so we won't ask for confirmation if (theEvent->flags & NX_CONTROLMASK) { if ([matrix cellCount] > 1) { // To avoid removing it from the view hierarchy while it is still lockFocused [self perform:@selector(removeCell:) with:[matrix selectedCell] afterDelay:0 cancelPrevious:YES]; } else { // They have just thrown away the last item on this menu - let's get rid of the menu itself id itemList = [supermenu itemList]; int i; for (i = 0; i < [itemList cellCount]; i++) { id thisCell = [itemList cellAt:i :0]; if((strcmp([self title], [thisCell title]) == 0) && ([thisCell tag] == 42131)) { // We have found the cell which controls us [itemList removeRowAt:i andFree:YES]; [supermenu setItemList:itemList]; [supermenu display]; // The following doesn't work for some reason - when you click on the main menu again, it tells you that it // is trying to send the message isSelectable to a freed object. I don't understand! // [self perform:@selector(free) with:nil afterDelay:10 cancelPrevious:YES]; [self perform:@selector(close) with:nil afterDelay:10 cancelPrevious:YES]; return self; } } } } else { [super mouseDown:theEvent]; } return self; } // methods to be the destination of a dragging operation - (NXDragOperation)draggingEntered:sender { return NX_DragOperationCopy; } - (BOOL)prepareForDragOperation:sender { return YES; } - (BOOL)performDragOperation:sender { // Here is where we do the real work id pboard = [sender draggingPasteboard]; NXStream *stream; NXTypedStream *ts; id newCell; // Read the dragged cell from the pasteboard stream = [pboard readTypeToStream:MHMenuCellPboardType]; ts = NXOpenTypedStream(stream, NX_READONLY); newCell = NXReadObject(ts); NXCloseTypedStream(ts); NXCloseMemory(stream, NX_FREEBUFFER); // Now add the cell to the end of the menu // This could be enhanced to note where they dropped and insert a cell at the appropriate place [matrix addRow]; [matrix putCell:newCell at:[matrix cellCount]-1 :0]; [self setItemList:matrix]; [self display]; return YES; } // Done with a performWith... to avoid lockFocus problems - removeCell:aCell { int row, col; [matrix getRow:&row andCol:&col ofCell:aCell]; [matrix removeRowAt:row andFree:YES]; [self setItemList:matrix]; [self display]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.