home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.bin / SourceCode / MiscKit1.2.6 / Source / MiscExplodingMenu.m < prev    next >
Encoding:
Text File  |  1994-05-15  |  4.7 KB  |  197 lines

  1. /*************************************************************************
  2. *    Copyright (c) 1994 Stone Design Corp.  All rights reserved. 
  3. *    programmer:    Andrew C. Stone
  4. *    File name:    MiscExplodingMenu.h
  5. *    Date:        May 2 1994 
  6. *    Purpose:    To show and hide all the menus in your application 
  7. *     This code may be used freely provided you leave this copyright in place
  8. *   This code is licensed under the terms of the MiscKit license.
  9. ***************************************************************************/
  10.  
  11. #import <misckit/MiscExplodingMenu.h>
  12. #import <objc/NXBundle.h>
  13. #import <appkit/Application.h>
  14. #import <appkit/Matrix.h>
  15. #import <appkit/MenuCell.h>
  16.  
  17. #define EXPLODE_TITLE NXLocalizedStringFromTable("stoneLib","Show Menus",NULL,"Show Menus menu title to show all of the menus in an app.")
  18.  
  19. #define IMPLODE_TITLE NXLocalizedStringFromTable("stoneLib","Hide Menus",NULL,"Hide Menus menu title")
  20.  
  21. #define SERVICES_TITLE NXLocalizedStringFromTable("stoneLib","Services",NULL,"Services menu title")
  22.  
  23. // Menu needs to be alerted when you rip off a menu so that it gets the close
  24. // box
  25.  
  26. @interface Menu(MyMenu)
  27. - setAttached;
  28. @end
  29.  
  30. @implementation Menu(MyMenu)
  31. - setAttached;
  32. {
  33.     menuFlags.attached = 1;
  34.     return self;
  35. }
  36. @end
  37.  
  38.  
  39. @implementation MiscExplodingMenu
  40.  
  41. static float largest;
  42.  
  43. + sharedInstance
  44. {
  45.     static id sharedInstance = nil;
  46.  
  47.     if (sharedInstance) {
  48.         return sharedInstance;
  49.     } else {
  50.         NXZone *zone = NXApp ? [NXApp zone] : NXDefaultMallocZone();
  51.     sharedInstance=[[super allocFromZone:zone] init];
  52.     }
  53.     
  54.     return sharedInstance;
  55. }
  56.  
  57. + new
  58. {
  59.     return [self sharedInstance];
  60. }
  61.  
  62. - free
  63. {
  64.     return self;
  65. }
  66.  
  67. - init
  68. {
  69.     [super init];
  70.     return self;
  71. }
  72.  
  73. - recursiveExplode:(Menu *)menu where:(float *)left :(float *)y not:orig
  74. {
  75.     id list,sub;
  76.     int i,count;
  77.     NXRect frame;
  78.     float wid;
  79.     NXEvent bogusEvent;
  80.     NXSize sz;
  81.     
  82.     [NXApp getScreenSize:&sz];
  83.     
  84.     /* if we get to services menu, stop, else leaves poop */
  85.     if (!strcmp([menu title], SERVICES_TITLE)) return self;
  86.     /* this line is required because NEXT does not translate the services menu.. */
  87.     if (!strcmp([menu title], "Services")) return self;
  88.     
  89.     /* first, emulate a move to get the closebox since there is no UI to do so */    
  90.     
  91.     [menu getFrame:&frame];
  92.     wid = frame.size.width;
  93.     
  94.     // this caused more problems than it was worth! so let's add a closebox
  95.     if (menu != [NXApp mainMenu] /* && menu != orig */) {
  96.     [menu setAttached];
  97.     
  98.     bogusEvent.location.x = frame.origin.x + 3.;    // must be different
  99.     bogusEvent.location.y = frame.origin.y + 3.;    // ditto
  100.     [menu windowMoved:&bogusEvent];
  101.     
  102.     [menu moveTopLeftTo:*left :*y];
  103.     [menu orderFront:self];
  104.     }
  105.     if (wid+*left>sz.width) {
  106.     *left = 0.;
  107.     *y -= (largest);
  108.     [menu moveTopLeftTo:*left :*y];
  109.     *left += wid;
  110.     } else *left += wid;
  111.        
  112.     list = [menu itemList];
  113.     count = [list cellCount];
  114.     
  115.     for (i = 0;i<count;i++) {
  116.     if ([(sub =[list cellAt:i :0]) hasSubmenu]) {
  117.     [self recursiveExplode:[sub  target] where:left :y not:orig]; 
  118.     }
  119.     }
  120.     return self;
  121. }
  122.  
  123.  
  124. - recursiveImplode:menu not:parent
  125. {
  126.     id list,sub;
  127.     int i,count;
  128.     float top;
  129.     BOOL isTornOff;
  130.     NXRect r;
  131.     NXSize sz;
  132.     
  133.     [menu getFrame:&r];
  134.     [NXApp getScreenSize:&sz];
  135.     
  136.     top = r.origin.y+r.size.height;
  137.     isTornOff =!(((sz.height - top) <1.) || top == sz.height -largest ||
  138.                 top == sz.height - 2*largest);
  139.     
  140.     list = [menu itemList];
  141.     count = [list cellCount];
  142.     for (i = 0;i<count;i++) {
  143.     if ([(sub =[list cellAt:i :0]) hasSubmenu]) {
  144.     [self recursiveImplode:[sub target] not:parent]; 
  145.     }
  146.     }
  147.     
  148.     /* If it has not been moved or is not NXApp or parent, close it */
  149.     
  150.     if (!isTornOff && menu != [NXApp mainMenu] && menu!=parent) [menu close];
  151.     
  152.     return self;
  153. }
  154.  
  155.  
  156. - _explodeMenus:sender
  157. {
  158.     const char *which = [[sender selectedCell]title];
  159.     if (which) {
  160.     if (!strcmp(which,EXPLODE_TITLE)) {
  161.         NXSize sz;
  162.         float x = -1.,y;
  163.         NXRect r;
  164.         
  165.         [[NXApp mainMenu]getFrame:&r];
  166.         [NXApp getScreenSize:&sz];
  167.         y = sz.height;
  168.         
  169.         largest = r.size.height +2.;
  170.         [sender setTitle:IMPLODE_TITLE at:[sender selectedRow] :0];
  171.         [self recursiveExplode:(Menu *)[NXApp mainMenu] where:&x :&y
  172.             not:[sender window]];    
  173.         [[sender window] display];
  174.     }
  175.     else {
  176.         [self recursiveImplode:[NXApp mainMenu] not:[sender window]];
  177.         [sender setTitle:EXPLODE_TITLE at:[sender selectedRow] :0];
  178.         [[sender window] display];
  179.     }
  180.     }
  181.     return self;
  182. }
  183.  
  184.  
  185.  
  186. /* FINALLY: actual called routine */
  187. /* this delay stuff sort of solves the problem..... */
  188. - explodeMenus:sender 
  189. {
  190.     [self perform:@selector(_explodeMenus:) with:sender
  191.         afterDelay:.01 cancelPrevious:YES];
  192.     return self;
  193. }
  194.  
  195.  
  196. @end
  197.