This is MiscExplodingMenu.m in view mode; [Download] [Up]
/************************************************************************* * Copyright (c) 1994 Stone Design Corp. All rights reserved. * programmer: Andrew C. Stone * File name: MiscExplodingMenu.h * Date: May 2 1994 * Purpose: To show and hide all the menus in your application * This code may be used freely provided you leave this copyright in place * This code is licensed under the terms of the MiscKit license. ***************************************************************************/ #import <misckit/MiscExplodingMenu.h> #import <objc/NXBundle.h> #import <appkit/Application.h> #import <appkit/Matrix.h> #import <appkit/MenuCell.h> #define EXPLODE_TITLE NXLocalizedStringFromTable("MiscKit","Show Menus",NULL,"Show Menus menu title to show all of the menus in an app.") #define IMPLODE_TITLE NXLocalizedStringFromTable("MiscKit","Hide Menus",NULL,"Hide Menus menu title") #define SERVICES_TITLE NXLocalizedStringFromTable("MiscKit","Services",NULL,"Services menu title") // Menu needs to be alerted when you rip off a menu so that it gets the close // box @interface Menu(MyMenu) - setAttached; @end @implementation Menu(MyMenu) - setAttached; { menuFlags.attached = 1; return self; } @end @implementation MiscExplodingMenu static float largest; + sharedInstance { static id sharedInstance = nil; if (sharedInstance) { return sharedInstance; } else { NXZone *zone = NXApp ? [NXApp zone] : NXDefaultMallocZone(); sharedInstance=[[super allocFromZone:zone] init]; } return sharedInstance; } + new { return [self sharedInstance]; } - free { return self; } - init { [super init]; return self; } - recursiveExplode:(Menu *)menu where:(float *)left :(float *)y not:orig { id list,sub; int i,count; NXRect frame; float wid; NXEvent bogusEvent; NXSize sz; [NXApp getScreenSize:&sz]; /* if we get to services menu, stop, else leaves poop */ if (!strcmp([menu title], SERVICES_TITLE)) return self; /* this line is required because NEXT does not translate the services menu.. */ if (!strcmp([menu title], "Services")) return self; /* first, emulate a move to get the closebox since there is no UI to do so */ [menu getFrame:&frame]; wid = frame.size.width; // this caused more problems than it was worth! so let's add a closebox if (menu != [NXApp mainMenu] /* && menu != orig */) { [menu setAttached]; bogusEvent.location.x = frame.origin.x + 3.; // must be different bogusEvent.location.y = frame.origin.y + 3.; // ditto [menu windowMoved:&bogusEvent]; [menu moveTopLeftTo:*left :*y]; [menu orderFront:self]; } if (wid+*left>sz.width) { *left = 0.; *y -= (largest); [menu moveTopLeftTo:*left :*y]; *left += wid; } else *left += wid; list = [menu itemList]; count = [list cellCount]; for (i = 0;i<count;i++) { if ([(sub =[list cellAt:i :0]) hasSubmenu]) { [self recursiveExplode:[sub target] where:left :y not:orig]; } } return self; } - recursiveImplode:menu not:parent { id list,sub; int i,count; float top; BOOL isTornOff; NXRect r; NXSize sz; [menu getFrame:&r]; [NXApp getScreenSize:&sz]; top = r.origin.y+r.size.height; isTornOff =!(((sz.height - top) <1.) || top == sz.height -largest || top == sz.height - 2*largest); list = [menu itemList]; count = [list cellCount]; for (i = 0;i<count;i++) { if ([(sub =[list cellAt:i :0]) hasSubmenu]) { [self recursiveImplode:[sub target] not:parent]; } } /* If it has not been moved or is not NXApp or parent, close it */ if (!isTornOff && menu != [NXApp mainMenu] && menu!=parent) [menu close]; return self; } - _explodeMenus:sender { const char *which = [[sender selectedCell]title]; if (which) { if (!strcmp(which,EXPLODE_TITLE)) { NXSize sz; float x = -1.,y; NXRect r; [[NXApp mainMenu]getFrame:&r]; [NXApp getScreenSize:&sz]; y = sz.height; largest = r.size.height +2.; [sender setTitle:IMPLODE_TITLE at:[sender selectedRow] :0]; [self recursiveExplode:(Menu *)[NXApp mainMenu] where:&x :&y not:[sender window]]; [[sender window] display]; } else { [self recursiveImplode:[NXApp mainMenu] not:[sender window]]; [sender setTitle:EXPLODE_TITLE at:[sender selectedRow] :0]; [[sender window] display]; } } return self; } /* FINALLY: actual called routine */ /* this delay stuff sort of solves the problem..... */ - explodeMenus:sender { [self perform:@selector(_explodeMenus:) with:sender afterDelay:.01 cancelPrevious:YES]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.