/* 
** A Popup Menu is a window which is sized so that the menu bar selections
** are arranged vertically, giving the appearance of a menu item popup.  The
** title is the name of the popup.
 */!!

inherit(Window, #PopupMenu, #(popSize  /* point: width@height */
sizeRect ), 2, nil)!!

now(class(PopupMenu))!!

/* 12/10/92 - PUBLIC
  Build and return a popup menu window.  The window is sized so 
  that the menu appears vertically.
  NOTES: title is a string
         data = #(#<item-string, id, selector>, #<...>)
*/
Def new(self, title, data, parent, ulCorner /* ulCorner is a point */ 
       | maxLen, tmp, winSize, popSize, newWindow, newMenu tm hdc tmHeight tmWidth)
{ 
  /* 
  ** Calculate window size:
  **  [A] Find may string length over title+pad and item-strings.
  **  [B] size is ( max_elt_size * elt_width )@( #_elts * elt_height )
  */
  
  /* assume bar select box is 3 characters wide, so title length += 6 */
  maxLen := 4 + size(title) ;
  do(data,
  {using(elem)
    if ( (tmp := size(elem[0])) > maxLen)
      then maxLen := tmp ;
    endif;
    
  });
  
  /* assume font width is w:8 and height is h:20
  ** popSize := (maxLen * w) @ (height(data)+height(title) * h) ;
  **             ==> width@height == deltaX@deltaY
  */
  tm := new(Struct, 32);
  Call GetTextMetrics(hdc := getContext(TheToolBarPresenter), tm);
  Call SelectObject(hdc, Call GetStockObject(SYSTEM_FIXED_FONT));
  tmWidth  := asInt(wordAt(tm, 10));
  tmHeight := asInt(wordAt(tm, 8)) + asInt(wordAt(tm, 0));
  Call SelectObject(hdc, Call GetStockObject(SYSTEM_FONT));
  releaseContext(TheToolBarPresenter, hdc);
 
  tmp := new(Point) ;
  if (x(screenSize()) > 800)
    /* magic numbers don't mess */
    setX(tmp, ((maxLen + 1) * tmWidth) ) ;
    setY(tmp, ((size(data) * (tmHeight + (tmHeight/3))) + tmHeight + tmHeight/2 +1));
  else
    setX(tmp, ((maxLen + 1) * tmWidth) ) ;
    setY(tmp, ((size(data)) * (tmHeight + (tmHeight/3))) + (2*tmHeight)/3  ) ;
  endif;
  popSize := tmp ;
  
  /*
  **  Pad out names to max length so that Windows does not 
  **  "double up" short ones.
  */
  
 do(data,
   {using(elem | siz)
    siz := size(elem[0]) ;
    if (siz < maxLen) then
      elem[0] := replace(elem[0],
          "                    ",  /* blanks for insert */
          0,                       /* blanks start */
          (maxLen - siz + 1),      /* blanks end */
          siz,                     /* from */
          maxLen                   /* to */
          );  
    endif; 
  }); 
  
    
  /*
  ** Build (popup) window and its menu.
  */
  
  tmp       := new(Rect) ;    /* calculate position rectangle for window */
  setLeft(  tmp, x(ulCorner)) ;
  setRight( tmp, x(ulCorner) + x(popSize) ) ;
  setTop(   tmp, y(ulCorner)) ;
  setBottom(tmp, y(ulCorner) + y(popSize) ) ;
  
  newWindow := newStyle(self:ancestor, parent, nil, title, tmp, nil, 
    WS_POPUP bitOr WS_CAPTION bitOr WS_SYSMENU); 
  newMenu   := create(new(Menu), newWindow) ;
  setPermanentRect(newWindow, tmp);
  
  /* Add the menu items */
  do(data,
    {using(elem)
      addItem(newMenu, new(MenuItem, elem[0], elem[1], elem[2])) ;
    });
  setDynamicMenu(newWindow, newMenu);
  
  /*
  ** Return the window (**not** shown)
  */
  
  ^newWindow

}
!!

now(PopupMenu)!!

/* 10/12/1993 11:14 */
Def WM_KEYDOWN(self, wp, lp)
{ 
  if (wp == 27) /* ESC key */ then
    close(self); 
  endif;
}
!!

/* 12/10/92 - PRIVATE
  Do not allow user resize popup window.
*/
Def WM_SIZE(self, wP, lP)
{ 
  if sizeRect then
    setCRect(self, sizeRect);
    moveWindow(self);
  endif;  
}!!

/* 12/10/1992 15:04 - PRIVATE
  Save the setup rectangle.
*/
Def setPermanentRect(self, newRect)
{ 
  sizeRect := newRect;
}
!!

/* need to clean up in conjunction with parent window */
Def close(self)
{ 
  destroyPopup(self, "dummy");
}
!!

/* this menu just dispatches operations to parent 
   NOTES: Nghia - 12/10/93
   Clear ESC key before processing command.
*/
Def command(self, item, lP | msg)
{ 
  if msg := action(menu, item)  then /* if action not "nil" */
    /* Clear ESC key */
    if (TaskLibClass$Inst)
      checkAbort(TaskLibClass$Inst);
    endif;
    if (msg = #destroyPopup) then
      ^perform(self, item, msg); /* destroy is local */
    else
      destroyPopup( self, msg ) ;
      ^perform(parent, item, msg); /* else for parent */
    endif;
  endif;
}
!!

/* delete the popUp Menu */
Def destroyPopup(self, msg)
{ 
  if (self.hWnd) then
    destroy(self);
  endif;
  if parent then
    nilifyPopWindow(parent);
  endif;  
}
!!

/* add dynamic menu */
Def setDynamicMenu(self, aMenu)
{ menu := aMenu;
}
!!

/* draw menu last */
Def update(self)
{ 
  update(self:ancestor) ;
  drawMenu(self) ;
}
!!