unit fOMNavA;

{$ASSERTIONS OFF}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Buttons, Grids, StdCtrls, ORCtrls, ExtCtrls, uConst, rOrders, uOrders, fFrame;

type
  TfrmOMNavA = class(TForm)
    pnlTool: TPanel;
    cmdDone: TORAlignButton;
    grdMenu: TCaptionStringGrid;
    cmdPrev: TBitBtn;
    cmdNext: TBitBtn;
    procedure FormActivate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure grdMenuDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure grdMenuKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure grdMenuMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure grdMenuMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure grdMenuMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pnlToolMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pnlToolMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure pnlToolMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure cmdDoneClick(Sender: TObject);
    procedure cmdPrevClick(Sender: TObject);
    procedure cmdNextClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure grdMenuKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormResize(Sender: TObject);
  private
    FOrderingMenu: Integer;
    FLastCol: Integer;
    FLastRow: Integer;
    FMouseDown: Boolean;
    FCtrlUp: Boolean;
    FSelecting: Boolean;
    FOrderMenuItem: TOrderMenuItem;
    FMenuHits: TList; {of TOrderMenu}
    FStack: TList; {of TMenuPath}
    FQuickBitmap: TBitmap;
    FOrigPoint: TPoint;
    FStartPoint: TPoint;
    FFormMove: Boolean;
    FKeyVars: string;
    FDelayEvent: TOrderDelayEvent;
    FMenuStyle: Integer;
    FRefNum: Integer;
    FSelectList: TList; {of TOrderMenuItem}
    FTheShift: TShiftState;
    procedure ActivateDialog(AnItem: TOrderMenuItem);
    procedure AddToSelectList(AnItem: TOrderMenuItem);
    procedure ClearMenuGrid;
    function DialogNotDisabled(DlgIEN: Integer): Boolean;
    procedure DoSelectList;
    function FindOrderMenu(AMenu: Integer): TOrderMenu;
    procedure PlaceMenuItems;
    procedure SetNavButtons;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure UMDestroy(var Message: TMessage);    message UM_DESTROY;
  public
    procedure CreateParams(var Params: TCreateParams); override;
    procedure SetEventDelay(AnEvent: TOrderDelayEvent);
    procedure SetNewMenu(MenuIEN: Integer; AnOwner: TComponent; ARefNum: Integer);
    procedure ResizeFont;
    property RefNum: Integer read FRefNum write FRefNum;
  end;

var
  frmOMNavA: TfrmOMNavA;

implementation

{$R *.DFM}

uses rODBase, ORFn, fODBase,fODGen, fODAuto, fOMVerify, uCore, rMisc, uODBase,
  fOrders, uAccessibleStringGrid;

const
  TX_NOFORM    = 'This selection does not have an associated windows form.';
  TC_NOFORM    = 'Missing Form ID';
  TX_ODACTIVE  = 'An ordering dialog is already active.';
  TC_ODACTIVE  = 'Unable to Select Item';
  TX_QO_NOSAVE = 'Unexpected error - it was not possible to save this order.';
  TC_QO_NOSAVE = 'Unable to Save Quick Order';
  TC_DISABLED  = 'Item Disabled';

type
  TMenuPath = class
    IENList: array of Integer;
    OwnedBy: TComponent;
    RefNum:  Integer;
    Current: Integer;
  end;

procedure TfrmOMNavA.ClearMenuGrid;
var
  ACol, ARow: Integer;
begin
  with grdMenu do
  begin
    for ACol := 0 to ColCount - 1 do for ARow := 0 to RowCount - 1 do
    begin
      Objects[ACol, ARow] := nil;
      Cells[ACol, ARow] := '';
    end;
    RowCount := 1;
    ColCount := 1;
    Cells[0, 0] := '';
  end;
end;

function TfrmOMNavA.FindOrderMenu(AMenu: Integer): TOrderMenu;
{ searchs the menu cache (FMenuHits) for a menu.  If not there, load the menu from the server. }
var
  i: Integer;
  AnOrderMenu: TOrderMenu;
begin
  i := 0;
  Result := nil;
  while (i < FMenuHits.Count) and (Result = nil) do          // search the menu cache
  begin
    AnOrderMenu := TOrderMenu(FMenuHits.Items[i]);
    if AnOrderMenu.IEN = AMenu then Result := AnOrderMenu;
    Inc(i);
  end;
  if Result = nil then                                       // load new menu from server
  begin
    AnOrderMenu := TOrderMenu.Create;
    AnOrderMenu.IEN := AMenu;
    AnOrderMenu.MenuItems := TList.Create;
    LoadOrderMenu(AnOrderMenu, AMenu);
    FMenuHits.Add(AnOrderMenu);
    Result := AnOrderMenu;
  end;
end;

procedure TfrmOMNavA.PlaceMenuItems;
{ places the menu items in the proper grid cells }
var
  i: Integer;
  OrderMenu: TOrderMenu;
  OrderMenuItem: TOrderMenuItem;
begin
  ClearMenuGrid;
  OrderMenu := FindOrderMenu(FOrderingMenu);
  if OrderMenu = nil then Exit;
  pnlTool.Caption  := OrderMenu.Title;
  grdMenu.ColCount := OrderMenu.NumCols;
  FKeyVars         := OrderMenu.KeyVars;
  grdMenu.DefaultColWidth := (grdMenu.ClientWidth div grdMenu.ColCount) - 1;
  with OrderMenu.MenuItems do for i := 0 to Count - 1 do
  begin
    OrderMenuItem := TOrderMenuItem(Items[i]);
    with grdMenu do
    begin
      if OrderMenuItem.Row >= RowCount then RowCount := OrderMenuItem.Row + 1;
      if (OrderMenuItem.Col > -1) and (OrderMenuItem.Row > -1) then
      begin
        Cells[OrderMenuItem.Col, OrderMenuItem.Row] := OrderMenuItem.ItemText;
        Objects[OrderMenuItem.Col, OrderMenuItem.Row] := OrderMenuItem;
      end; {if OrderMenuItem}
    end; {with grdMenu}
  end; {for i}
  with grdMenu do if VisibleRowCount < RowCount then
    ColWidths[ColCount - 1] := DefaultColWidth - GetSystemMetrics(SM_CXVSCROLL);
end;

procedure TfrmOMNavA.SetNewMenu(MenuIEN: Integer; AnOwner: TComponent; ARefNum: Integer);
{ Creates a new 'starting' menu.  For initial menu or menu from inside order set. }
var
  NewMenuPath: TMenuPath;
begin
  NewMenuPath := TMenuPath.Create;
  SetLength(NewMenuPath.IENList, 1);
  NewMenuPath.IENList[0] := MenuIEN;
  NewMenuPath.OwnedBy := AnOwner;
  NewMenuPath.RefNum  := ARefNum;
  NewMenuPath.Current := 0;
  FStack.Add(NewMenuPath);
  FOrderingMenu := MenuIEN;  // sets new starting point here
  SetNavButtons;
  PlaceMenuItems;            // displays menu, with nav & done buttons set
  PushKeyVars(FKeyVars);
  Self.Enabled := True;
end;

{ menu navigation }

procedure TfrmOMNavA.SetNavButtons;
var
  MenuPath: TMenuPath;
begin
  with FStack do MenuPath := TMenuPath(Items[Count - 1]);
  cmdPrev.Enabled := MenuPath.Current > 0;
  cmdNext.Enabled := MenuPath.Current < High(MenuPath.IENList);
  if FStack.Count > 1 then cmdDone.Caption := 'Next' else cmdDone.Caption := 'Done';
  pnlTool.Invalidate;
end;

procedure TfrmOMNavA.cmdPrevClick(Sender: TObject);
var
  MenuPath: TMenuPath;
begin
  with FStack do MenuPath := TMenuPath(Items[Count - 1]);
  Dec(MenuPath.Current);
  FOrderingMenu := MenuPath.IENList[MenuPath.Current];
  SetNavButtons;
  PlaceMenuItems;
  PopKeyVars;
end;

procedure TfrmOMNavA.cmdNextClick(Sender: TObject);
var
  MenuPath: TMenuPath;
begin
  with FStack do MenuPath := TMenuPath(Items[Count - 1]);
  Inc(MenuPath.Current);
  FOrderingMenu := MenuPath.IENList[MenuPath.Current];
  SetNavButtons;
  PlaceMenuItems;
  PushKeyVars(FKeyVars);
end;

procedure TfrmOMNavA.cmdDoneClick(Sender: TObject);
var
  MenuPath: TMenuPath;
begin
  if FSelecting then Exit;
  with FStack do MenuPath := TMenuPath(Items[Count - 1]);
  with FStack do Delete(Count - 1);
  if FStack.Count = 0 then Close;
  with MenuPath do if (OwnedBy <> nil) and (OwnedBy is TWinControl)
    then SendMessage(TWinControl(OwnedBy).Handle, UM_DESTROY, RefNum, 0);
  PopKeyVars(MenuPath.Current + 1);
  MenuPath.Free;
  if FStack.Count > 0 then
  begin
    with FStack do MenuPath := TMenuPath(Items[Count - 1]);
    FOrderingMenu := MenuPath.IENList[MenuPath.Current];
    SetNavButtons;
    PlaceMenuItems;
  end;
end;

{ Form methods }

procedure TfrmOMNavA.FormCreate(Sender: TObject);
begin
  FLastCol := -1;
  FLastRow := -1;
  FMenuStyle := OrderMenuStyle;
  FMenuHits := TList.Create;
  FStack := TList.Create;
  FSelectList := TList.Create;
  FQuickBitmap := TBitmap.Create;
  FQuickBitmap.LoadFromResourceName(hInstance, 'BMP_QO_THIN');
  NoFresh := True;
  ResizeFont;
  TAccessibleStringGrid.WrapControl(grdMenu);
end;

procedure TfrmOMNavA.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do Style := (Style or WS_POPUP) and (not WS_DLGFRAME);
  //with Params do Style := WS_THICKFRAME or WS_POPUP or WS_BORDER;
end;

procedure TfrmOMNavA.UMDestroy(var Message: TMessage);
{ sent by ordering dialog when it is closing }
begin
  Self.Enabled := True;
  Self.SetFocus;
end;

procedure TfrmOMNavA.FormDestroy(Sender: TObject);
var
  i, j: Integer;
  OrderMenu: TOrderMenu;
  OrderMenuItem: TOrderMenuItem;
begin
  TAccessibleStringGrid.UnwrapControl(grdMenu);
  ClearMenuGrid;
  for i := 0 to FMenuHits.Count - 1 do
  begin
    OrderMenu := TOrderMenu(FMenuHits.Items[i]);
    for j := 0 to OrderMenu.MenuItems.Count - 1 do
    begin
      OrderMenuItem := TOrderMenuItem(OrderMenu.MenuItems.Items[j]);
      OrderMenuItem.Free;
    end;
    OrderMenu.MenuItems.Clear;
    OrderMenu.MenuItems.Free;
    OrderMenu.Free;
  end;
  FMenuHits.Free;
  Assert(FStack.Count = 0);
  FStack.Free;
  Assert(FSelectList.Count = 0);
  FSelectList.Free;
  FQuickBitmap.Free;
  DestroyingOrderMenu;
  if (frmOrders.TheCurrentView<>nil) and (frmOrders.TheCurrentView.EventDelay.PtEventIFN>0)
    and (IsCompletedPtEvt(frmOrders.TheCurrentView.EventDelay.PtEventIFN)) then
    SendMessage(frmOrders.handle,UM_EVENTOCCUR,0,0);
end;

procedure TfrmOMNavA.FormActivate(Sender: TObject);
begin
  // do we need to bring something to front here?
end;

procedure TfrmOMNavA.FormClose(Sender: TObject; var Action: TCloseAction);
var
  MenuPath: TMenuPath;
begin
  while FStack.Count > 0 do
  begin
    with FStack do MenuPath := TMenuPath(Items[Count - 1]);
    with MenuPath do if (OwnedBy <> nil) and (OwnedBy is TWinControl)
      then SendMessage(TWinControl(OwnedBy).Handle, UM_DESTROY, RefNum, 0);
    PopKeyVars(MenuPath.Current + 1);
    MenuPath.Free;
    with FStack do Delete(Count - 1);
  end;
  SaveUserBounds(Self);
  NoFresh := False;
  Action := caFree;
end;

procedure TfrmOMNavA.SetEventDelay(AnEvent: TOrderDelayEvent);
begin
  FDelayEvent := AnEvent;
end;

procedure TfrmOMNavA.grdMenuDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
  State: TGridDrawState);
{ Draws each cell in the grid based on characteristics in associated OrderMenuItem object. }
const
  QO_BMP_WIDTH = 15;
var
  OrderMenuItem: TOrderMenuItem;
  AMnemonic: string;
  MneRect, ItmRect: TRect;
  MneWidth: integer;
begin
  //if Sender = ActiveControl then Exit;
  //if not (gdSelected in State) then Exit;
  with Sender as TStringGrid do with Canvas do
  begin
    MneWidth := TextWidthByFont(Handle, 'MMM');
    OrderMenuItem := TOrderMenuItem(grdMenu.Objects[ACol, ARow]);
    if (OrderMenuItem <> nil) then with OrderMenuItem do
    begin
      Font.Style := [];
      Font.Color := clWindowText;
      if Selected    then
      begin
         if ColorToRGB(clWindowText) = ColorToRGB(clBlack) then
          Font.Color := clBlue;
        Font.Style := Font.Style + [fsUnderline];
      end;
      if Display = 2 then
        Font.Style := Font.Style + [fsBold];
    end;
    Brush.Color := Color;
    if (FMenuStyle = 0) and
      ((OrderMenuItem = nil) or ((OrderMenuItem <> nil) and (OrderMenuItem.Display <> 2))) then
    begin
      if OrderMenuItem <> nil then AMnemonic := OrderMenuItem.Mnemonic else AMnemonic := '';
      FillRect(Rect);
      MneRect.Left := Rect.Left + QO_BMP_WIDTH;
      MneRect.Right := MneRect.Left + MneWidth;
      MneRect.Top := Rect.Top + 2;
      MneRect.Bottom := Rect.Bottom;
      ItmRect.Left := Rect.Left + QO_BMP_WIDTH + MneWidth + 1;
      ItmRect.Right := Rect.Right;
      ItmRect.Top := Rect.Top + 2;
      ItmRect.Bottom := Rect.Bottom;
      TextRect(MneRect, MneRect.Left, MneRect.Top, AMnemonic);
      TextRect(ItmRect, ItmRect.Left, ItmRect.Top, Cells[ACol, ARow]);
    end
    else TextRect(Rect, Rect.Left + QO_BMP_WIDTH, Rect.Top + 2, Cells[ACol, ARow]);
    if (OrderMenuItem <> nil) and OrderMenuItem.AutoAck
      then Draw(Rect.Left + 2, Rect.Top + 2, FQuickBitmap);	{ draw bitmap }
    if gdSelected in State then
    begin
      Pen.Width := 1;
      if FMouseDown then Pen.Color := clBtnShadow    else Pen.Color := clBtnHighlight;
      MoveTo(Rect.Left,  Rect.Bottom - 1);
      LineTo(Rect.Left,  Rect.Top);
      LineTo(Rect.Right, Rect.Top);
      if FMouseDown then Pen.Color := clBtnHighlight else Pen.Color := clBtnShadow;
      LineTo(Rect.Right, Rect.Bottom);
      LineTo(Rect.Left,  Rect.Bottom);
    end;
  end;
end;

{ Mouse & Keyboard Handling }

procedure TfrmOMNavA.AddToSelectList(AnItem: TOrderMenuItem);
begin
  if AnItem = nil then Exit;
  FSelectList.Add(AnItem);
  FSelecting := True;
  cmdDone.Enabled := False;
end;

procedure TfrmOMNavA.DoSelectList;
var
  i: Integer;
  x: string;
  ItemList: TStringList;
  AMenuItem: TOrderMenuItem;
begin
  FSelecting := False;
  cmdDone.Enabled := True;
  if FSelectList.Count = 0 then Exit;
  ItemList := TStringList.Create;
  try
    for i := 0 to FSelectList.Count - 1 do
    begin
      AMenuItem := TOrderMenuItem(FSelectList[i]);
      if AMenuItem <> nil then
      begin
        x := IntToStr(AMenuItem.IEN) + U + AMenuItem.DlgType + U + AMenuItem.ItemText;
        ItemList.Add(x);
      end;
    end;
    if ItemList.Count > 0 then ActivateOrderList(ItemList, FDelayEvent, Self, 0, '', '');
  finally
    FSelectList.Clear;
    ItemList.Free;
  end;
end;

procedure TfrmOMNavA.grdMenuKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  //frmFrame.UpdatePtInfoOnRefresh;
  if Key in [VK_RETURN, VK_SPACE] then with grdMenu do
  begin
    if frmOrders <> nil then
    begin
       if (frmOrders.TheCurrentView<>nil) and (frmOrders.TheCurrentView.EventDelay.PtEventIFN>0)
         and IsCompletedPtEvt(frmOrders.TheCurrentView.EventDelay.PtEventIFN) then
       begin
         FDelayEvent.EventType := #0;
         FDelayEvent.EventIFN  := 0;
         FDelayEvent.TheParent := TParentEvent.Create;
         FDelayEvent.EventName := '';
         FDelayEvent.PtEventIFN := 0;
       end;
    end;
    //frmFrame.UpdatePtInfoOnRefresh;
    FOrderMenuItem := TOrderMenuItem(Objects[Col, Row]);
    if FOrderMenuItem.Display > 0 then FOrderMenuItem := nil;          // display only
    if FOrderMenuItem <> nil then
    begin
      FOrderMenuItem.Selected := True;
      if ssCtrl in Shift
        then AddToSelectList(FOrderMenuItem)
        else ActivateDialog(FOrderMenuItem);
      FOrderMenuItem := nil;
      Key := 0;
    end;
    if frmOrders <> nil then
    begin
       if (frmOrders.TheCurrentView<>nil) and (frmOrders.TheCurrentView.EventDelay.PtEventIFN>0)
         and IsCompletedPtEvt(frmOrders.TheCurrentView.EventDelay.PtEventIFN) then
       begin
         FDelayEvent.EventType := #0;
         FDelayEvent.EventIFN  := 0;
         FDelayEvent.TheParent := TParentEvent.Create;
         FDelayEvent.EventName := '';
         FDelayEvent.PtEventIFN := 0;
       end;
    end;
  end;
  if Key = VK_BACK then
  begin
    cmdPrevClick(Self);
    Key := 0;
  end;
  if Key = VK_ESCAPE then
  begin
    cmdDoneClick(Self);
    Key := 0;
  end;
end;

procedure TfrmOMNavA.grdMenuKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_CONTROL then
  begin
    if FMouseDown then FCtrlUp := True else DoSelectList;
  end;
end;

procedure TfrmOMNavA.grdMenuMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  ACol, ARow: Integer;
begin
  //frmFrame.UpdatePtInfoOnRefresh;
  if ssDouble in Shift then
  begin
    FTheShift := [ssDouble];
    Exit;  // ignore a double click
  end;
  if frmOrders <> nil then
  begin
    if (frmOrders.TheCurrentView<>nil) and (frmOrders.TheCurrentView.EventDelay.PtEventIFN>0)
      and IsCompletedPtEvt(frmOrders.TheCurrentView.EventDelay.PtEventIFN) then
    begin
      FDelayEvent.EventType := #0;
      FDelayEvent.EventIFN  := 0;
      FDelayEvent.TheParent := TParentEvent.Create;
      FDelayEvent.EventName := '';
      FDelayEvent.PtEventIFN := 0;
    end;
  end;
  //frmFrame.UpdatePtInfoOnRefresh;
  with grdMenu do
  begin
    MouseToCell(X, Y, ACol, ARow);
    if (ACol > -1) and (ARow > -1) and (ACol < grdMenu.ColCount) and (ARow < grdMenu.RowCount) then
    begin
      FMouseDown := True;
      FOrderMenuItem := TOrderMenuItem(Objects[ACol, ARow]);
      // check to see if this is a display only field
      if (FOrderMenuItem <> nil) and (FOrderMenuItem.Display > 0) then FOrderMenuItem := nil;
      if  FOrderMenuItem <> nil then FOrderMenuItem.Selected := True;
    end;
  end;
end;

procedure TfrmOMNavA.grdMenuMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  ACol, ARow: Integer;
begin
  grdMenu.MouseToCell(X, Y, ACol, ARow);
  if (ACol = FLastCol) and (ARow = FLastRow) then Exit;
  if (ACol > -1) and (ARow > -1) and (ACol < grdMenu.ColCount) and (ARow < grdMenu.RowCount) then
  begin
    FLastCol := ACol;
    FLastRow := ARow;
    grdMenu.Col := ACol;
    grdMenu.Row := ARow;
  end;
end;

procedure TfrmOMNavA.grdMenuMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if ssDouble in Shift then Exit;  // ignore a double click
  if ssDouble in FTheShift then
  begin
    FTheShift := [];
    Exit;
  end;

  FMouseDown := False;
  //grdMenu.Invalidate;
  // may want to check here to see if mouse still over the same item
  if ssCtrl in Shift then AddToSelectList(FOrderMenuItem) else
  begin
    if FCtrlUp then
    begin
      FCtrlUp := False;
      AddToSelectList(FOrderMenuItem);
      DoSelectList;
    end
    else ActivateDialog(FOrderMenuItem);
  end;
  FCtrlUp := False;
  FOrderMenuItem := nil;
  if frmOrders <> nil then
  begin
    if (frmOrders.TheCurrentView<>nil) and (frmOrders.TheCurrentView.EventDelay.PtEventIFN>0)
      and IsCompletedPtEvt(frmOrders.TheCurrentView.EventDelay.PtEventIFN) then
    begin
      FDelayEvent.EventType := #0;
      FDelayEvent.EventIFN  := 0;
      FDelayEvent.TheParent := TParentEvent.Create;
      FDelayEvent.EventName := '';
      FDelayEvent.PtEventIFN := 0;
    end;
  end;
end;

procedure TfrmOMNavA.CMMouseLeave(var Message: TMessage);
begin
  inherited;
  FLastCol := -1;
  FLastRow := -1;
end;

function TfrmOMNavA.DialogNotDisabled(DlgIEN: Integer): Boolean;
var
  x: string;
begin
  Result := True;
  x := OrderDisabledMessage(DlgIEN);
  if Length(x) > 0 then
  begin
    Result := False;
    InfoBox(x, TC_DISABLED, MB_OK);
  end;
end;

procedure TfrmOMNavA.ActivateDialog(AnItem: TOrderMenuItem);
var
  MenuPath: TMenuPath;
begin
  if AnItem = nil then Exit;
  case AnItem.DlgType of
  #0:  { ignore if no type, i.e., display header or blank };
  'A': ActivateAction(IntToStr(AnItem.IEN) + ';' + IntToStr(AnItem.FormID), Self, 0);
  'D': ActivateOrderDialog(IntToStr(AnItem.IEN), FDelayEvent, Self, 0);
  'M': begin
         // this simply moves to new menu, rather than open a new form as in ActivateOrderMenu
         if DialogNotDisabled(AnItem.IEN) then
         begin
           with FStack do MenuPath := TMenuPath(Items[Count - 1]);
           with MenuPath do
           begin
             Inc(Current);
             if Current > High(IENList) then SetLength(IENList, Current + 1);
             if Current <> AnItem.IEN then
             begin
               IENList := Copy(IENList, 0, Current + 1);
               IENList[Current] := AnItem.IEN;
             end;
             FOrderingMenu := AnItem.IEN;
             SetNavButtons;
             PlaceMenuItems;
             PushKeyVars(FKeyVars);
             with grdMenu do
               GoodNotifyWinEvent(EVENT_OBJECT_FOCUS, Handle, integer(OBJID_CLIENT), ColRowToIndex(Col,Row));
           end; {with MenuPath}
         end; {if}
       end; {'M'}
  'Q': ActivateOrderDialog(IntToStr(AnItem.IEN), FDelayEvent, Self, 0);
  'P': ShowMessage('Order Dialogs of type "Prompt" cannot be processed.');
  'O': begin
         // disable initially, since the 1st item in the set may be a menu
         Self.Enabled := False;
         if not ActivateOrderSet(IntToStr(AnItem.IEN), FDelayEvent, Self, 0)
           then Self.Enabled := True;
       end;
  else ShowMessage('Unknown Order Dialog type: ' + AnItem.DlgType);
  end; {case}
end;

{ imitate caption bar using panel at top of form }

procedure TfrmOMNavA.pnlToolMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button <> mbLeft then Exit;
  FStartPoint := TControl(Sender).ClientToScreen(Point(X, Y));
  FOrigPoint  := Point(Left, Top);
  FFormMove   := True;
end;

procedure TfrmOMNavA.pnlToolMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  NewPoint: TPoint;
begin
  if FFormMove then
  begin
    NewPoint := TControl(Sender).ClientToScreen(Point(X, Y));
    SetBounds(FOrigPoint.X - (FStartPoint.X - NewPoint.X),
              FOrigPoint.Y - (FStartPoint.Y - NewPoint.Y), Width, Height);
  end;
end;

procedure TfrmOMNavA.pnlToolMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FFormMove := False;
end;

procedure TfrmOMNavA.FormResize(Sender: TObject);
begin
  grdMenu.DefaultColWidth := (grdMenu.ClientWidth div grdMenu.ColCount) - 1;
  grdMenu.Refresh;
end;

procedure TfrmOMNavA.ResizeFont;
begin
  ResizeAnchoredFormToFont(Self);
  grdMenu.Canvas.Font := grdMenu.Font;
end;

end.
