/* MDICLIEN.CLS - This class handles the creation and
  maintenance of an MDI Client window.  An MDI Client
  must be created with an MDIFrame as it's parent and
  should be automatically destroyed by the MDIFrame's
  default window procedure. */!!

inherit(Control, #MDIClient, #(childList activeChild windowMenu), 2, nil)!!

now(class(MDIClient))!!

Def newMDIClient(self, par, firstID)
{ ^init(createMDICLient(new(self:Behavior), par, style(self), firstID));
}!!

/* Return the default window style. */
Def style(self)
{ ^WS_CHILD bitOr WS_CLIPCHILDREN bitOr WS_VSCROLL bitOr WS_HSCROLL;
}!!

now(MDIClient)!!

Def deactivateMDIChild(self, theChild)
{ if activeChild == theChild
  then activeChild := nil;
  endif;
}!!

Def activateMDIChild(self, theChild)
{ activeChild := theChild;
}!!

/* Return a pointer to the child window specified by theHWnd */
Def activeChild(self)
{ ^activeChild;
}!!

/* Step through all of the applications child windows and make sure that
  they are ready to be closed, before closing the MDI Frame Window. */
Def closeAllMDIChildren(self | allClosed)
{ allClosed := true;
  do(copy(childList),
  {using(aChild)
     if shouldClose(aChild)
     then destroy(aChild);
     else allClosed := nil;
     endif;
  });
  ^allClosed;
}!!

/* Close the MDI child window associated with the window handle
  that is passed to this routine. */
Def closeMDIChild(self, theHWnd)
{ close(childList[theHWnd]);
}!!

/* Destroy the MDI Child window that is associated with the
  window handle that is passed in */
Def destroyMDIChild(self, theHWnd)
{ destroy(childList[theHWnd]);
}!!

/* Calling this method with a class name, caption text, and a rectangle
  in which to display the window will create a new MDI child.  It will
  then add that child windows pointer to the childList dictionary, keying
  it on the hWnd of that child. */
Def createMDIChild(self, childClass, wName, rect | theChild)
{ if theChild := new(childClass, self, nil, wName, rect)
  then
    if size(childList) == 0
    then enableMenus(parent);
      activeChild := theChild;
    endif;
    add(childList, getHWnd(theChild), theChild);
  endif;
  ^theChild;
}!!

Def init(self)
{ childList := new(Dictionary, 2);
}!!

/* Default for dialogs is to do nothing. Return 0
  to let Windows do normal processing.
  WARNING: Do not remove this method! May be redefined
  in descendants if they register a private window
  class with Windows for their dialogs. */
Def defWndProc(self, msgNum, wP, lP)
{ ^0;
}!!

/* This message is called every time an MDI Child makes a request to be
  destroyed.  The default procedure for the MDI Client will handle the
  destruction of the child window.  That childs pointer will then be
  removed from the child window dictionary of the frame window. */
Def WM_MDIDESTROY(self, wP, lP)
{ execWindowProc(self, #WM_MDIDESTROY, wP, lP);
  remove(childList, wP);
  if size(childList) == 0
  then activeChild := nil;
  endif;
  disableMenus(parent);
}!!

/* Make sure to remove the property created for the Client Window when
  it has been destroyed. */
Def WM_NCDESTROY(self, wP, lP)
{ Call RemoveProp(hWnd, asciiz("ActorOOP"));
}!!

/* Create a new MDI client window.  Certain parameters should be the same
  no matter the client window that is being created, thus these values
  have been hardcoded.  For example, MDIClient should not have a menu,
  will always be registered with the "mdiclient" class, and has it's
  position and size determined by the MDIFrame window. */
Def createMDICLient(self, par, style, firstChildID | clientStruct)
{ parent := par;
  windowMenu := Call CreatePopupMenu();
  Call AppendMenu(windowMenu, MF_STRING, 9997, asciiz("&Cascade"));
  Call AppendMenu(windowMenu, MF_STRING, 9998, asciiz("&Tile"));
  Call AppendMenu(windowMenu, MF_STRING, 9999, asciiz("&Arrange Icons"));
  Call InsertMenu(menuHandle(parent), -1, MF_POPUP, windowMenu, asciiz("&Windows"));
  clientStruct := new(Struct, 4);
  putWord(clientStruct, windowMenu, 0);
  putWord(clientStruct, firstChildID, 2);
  hWnd := Call CreateWindow(asciiz("mdiclient"), 0, style,
    0, 0, 0, 0, getHWnd(par), 0xCAC, HInstance, clientStruct);
  if hWnd = 0
  then alert(System, self, #windCreateError);
  endif;
  setActorProp(self);
  defProc := Call GetWindowLong(hWnd, -4);
  Call SetWindowLong(hWnd, -4, LpWFunc);
}!!
