/* The abstract superclass for the descendant windows that require a menu creation and processing capability.  A descendant window normally creates menu choices in the init method as:
                  initMenu(self) 
                      set up menu choices (see attachMenuChoices)
                      ...
                   drawMenu(self)
*/!!

inherit(Window, #AutomaticMenu, #(menuIdCount  /* counter for menu id assignment */
menuDict /* dictionary whose key is the menu name and value is the menu id number */
helpContextNumber
  /* help context number for this component */), 2, nil)!!

now(class(AutomaticMenu))!!

now(AutomaticMenu)!!

/* PUBLIC
   Enables a menu item.  Currently we don't support enabling of popup
   menus.
 */
Def enableMenuItemByPosition(self, position | menuId)
{ 
  enableMenuItem(menu(self), position);
}
!!

/* PUBLIC
   Disables a menu item.  Currently we don't support disabling of popup
   menus.
 */
Def disableMenuItemByPosition(self, position | menuId)
{ 
  disableMenuItemByPosition(menu(self), position);
}
!!

/* PUBLIC
   Grays a menu item.  Currently we don't support graying of popup
   menus.
 */
Def grayMenuItemByPosition(self, position | menuId)
{ 
  grayMenuItemByPosition(menu(self), position);
}
!!

/* PRIVATE
   Add new item to the menu bar.
 */
Def addMenu(self, item)
{ 
  addItem(menu(self),item);
}
!!

/* Construct window/help menu entries.  Context number is used for context-
   sensitive help.  Presenter name is placed in menu, so it should be one
   of the following:
     "&Source"
     "S&tack"
     "&Variable"
     "Stat&us"
     "&CPU"
     "&Memory"
     "Tr&ace"
     "Tri&gger"
     "S&hell"
     "&Event"
     "&Breakpoint"
     "&PowerViews"*/
Def addWindowAndHelp(self, presenterName, contextNumber | item)
{
  /* save context number */
  helpContextNumber := contextNumber;
  
  /* create menu */
  Call AppendMenu(menuHandle(self),MF_POPUP,windowsMenu(PreLauncher),
                  asciiz("&Windows"));
  incrMenuId(self);
  menuDict["&Help"] := menuId(self); 
  item := newPopup(MenuItem, "&Help");
  addItem(item, new(MenuItem, 
                    "Help &Index",       
                     601, 
                     #menuHelpContents));
  addItem(item, new(MenuItem, 
                    "&Help With Help",        
                     602, 
                     #menuHelpHelp));
  addItem(item, nil);
  addItem(item, new(MenuItem, 
                    "Help With " + presenterName,        
                     603, 
                     #menuHelpContext));
  addMenu(self,item);
}
!!

/* PUBLIC
   Attach the menu choices to the window.  An argument menu is a 
   Collection of (menuStr, symbol).  For example: 
      ("&File",#file) installs a single menu item.
   or ("&Edit", ((C&ut,#cut),(&Copy,#copy))) installs a popup "&Edit"
      with two menu selections. 
      
   There is no limit to the nesting.
   For each action symbol (i.e.: #file) the corresponding method
   must exist.
 */
Def attachMenuChoices(self, menus | item)
{ 
  do(menus, { using(aMenu)
    item := getMenuItem(self,aMenu);
    addMenu(self,item)  })
}
!!
/* PUBLIC
   Sets a check by a menu item.
 */
Def checkMenuItem(self, menuName)
{ 
  checkMenuItem(menu(self), getMenuId(self, menuName));
}
!!

/* PUBLIC */
Def close(self)
{ 
  removeWindowMenu(self);
  close(self:ancestor);
}
!!

/* PUBLIC
   Responds to the menu events.
 */
Def command(self, menuId, lp | msg)
{
  if msg := action(menu(self),menuId)   /* if menuId is defined */
    perform(self,msg);                  /* do the corresponding action */
  else   /* dynamic window menu dropdown. */
    if not(doAction(PreLauncher, menuId))
      command(self:ancestor, menuId, lp);
    endif ;
  endif;
}
!!

/* PUBLIC
   Disables a menu item.  Currently we don't support disabling of popup
   menus.
 */
Def disableMenuItem(self, menuName | menuId)
{ 
  menuId := getMenuId(self, menuName);
  if menuId <> -1
    disableMenuItem(menu(self), menuId);
  endif;
}
!!

/* PUBLIC
   Enables a menu item.  Currently we don't support enabling of popup
   menus.
 */
Def enableMenuItem(self, menuName | menuId)
{ 
  menuId := getMenuId(self, menuName);
  if menuId <> -1
    enableMenuItem(menu(self), menuId);
  endif;
}
!!

/* PRIVATE
   Return the menu Id.
 */
Def getMenuId(self, menuName)
{ 
  ^menuDict[menuName] cor -1;
}
!!

/*  PRIVATE
    Returns the newly created menuitem.  The aMenu argument is of the
    following format: (menuStr,symbol).  For example ("&File",#file) or
    can be recursively defined to handle pulldown and hierarchial menu.
 */
Def getMenuItem(self, aMenu | recurMenu)
{ if not(aMenu[0])  /* want to support adding a 'line' menu option. */ 
    ^nil;           /* i.e.: a menu item separator */
  endif;
  if class(aMenu[1]) = Symbol
    incrMenuId(self);
    menuDict[aMenu[0]] := menuId(self);
    ^new(MenuItem,aMenu[0],menuId(self),aMenu[1])
  else
    recurMenu := newPopup(MenuItem,aMenu[0]);
    do(aMenu[1],
    {using(subMenu)
      addItem(recurMenu,getMenuItem(self,subMenu));
    });
    ^recurMenu;
  endif;
}
    
!!

/* PUBLIC
   Grays a menu item.  Currently we don't support graying of popup
   menus.
 */
Def grayMenuItem(self, menuName | menuId)
{ 
  menuId := getMenuId(self, menuName);
  if menuId <> -1
    grayMenuItem(menu(self), menuId);
  endif;
}
!!

/* PRIVATE
   Increment the menu id counter.
 */
Def incrMenuId(self)
{ 
  menuIdCount := menuIdCount + 1;
}
!!

/* PUBLIC
   Initializes the menu creatation and setup process.
 */
Def initMenu(self)
{ 
  setMenuId(self,200);      /* initial value for menu id counter */
  menu := create(new(Menu),self);
  menuDict := new(Dictionary,10);
}
!!

/* PRIVATE
   Return the menu object.
 */
Def menu(self)
{ 
  ^menu;
}
!!

/* CLI */
Def menuAbout(self)
{
  if not(CLIULibraryClass$Inst) then
     ^nil;
  else
     showAboutBox(CLIULibraryClass$Inst);
  endif;
}!!

/* BUTTON */
Def menuHelpContents(self)
{
  contents(TheHelpObject, hWnd(self));
}!!

/* context-sensitive help */
Def menuHelpContext(self)
{
  contextNumber(TheHelpObject, hWnd(self), helpContextNumber);
}!!

/* CLI */
Def menuHelpHelp(self)
{
  help(TheHelpObject, hWnd(self));
}
!!

/* PRIVATE
   Return the menu Id counter value.
 */
Def menuId(self)
{ 
  ^menuIdCount;
}
!!

/* PRIVATE
   Set the menu Id counter.
 */
Def setMenuId(self, id)
{ 
  ^menuIdCount := id;
}
!!

/* PUBLIC
   Removes a check by a menu item.
 */
Def unCheckMenuItem(self, menuName)
{ 
  unCheckMenuItem(menu(self), getMenuId(self, menuName));
}
!!

Def WM_INITMENU(self, wp, lp) {
  ^WM_INITMENU(PreLauncher, wp, lp);
} 
!!
