/*************************************************************************
*	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
