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.