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.