ftp.nice.ch/pub/next/developer/resources/classes/misckit/MiscKit.1.10.0.s.gnutar.gz#/MiscKit/Source/MiscKit/MiscExplodingMenu.m

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.