home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- * 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("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 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
-