This is ExplodingMenu.m in view mode; [Download] [Up]
/************************************************************************* * Copyright (c) 1994 Stone Design Corp. All rights reserved. * programmer: Andrew C. Stone * File name: ExplodingMenu.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 ***************************************************************************/ #import "ExplodingMenu.h" #import <objc/NXBundle.h> #import <appkit/Application.h> #import <appkit/Matrix.h> #import <appkit/MenuCell.h> #define EXPLODE_TITLE NXLocalizedStringFromTable("stoneLib","Show Menus",NULL,"Show Menus menu title to show all of the menus in an app.") #define IMPLODE_TITLE NXLocalizedStringFromTable("stoneLib","Hide Menus",NULL,"Hide Menus menu title") #define SERVICES_TITLE NXLocalizedStringFromTable("stoneLib","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 ExplodingMenu 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; // Seems to be a problem for menus that are (completely/partially) off the screen. 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 close]; // if (!isTornOff && menu != [NXApp mainMenu] && menu!=parent) [menu close]; return ( self ); } - _explodeMenus:wanker { if (explodeMenus) { 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 ); } static BOOL explodeMenus; /* FINALLY: actual called routine */ /* this delay stuff sort of solves the problem..... */ - explodeMenus:(BOOL)explode { explodeMenus = explode; [self perform:@selector(_explodeMenus:) with:self 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.