///////////////////////////////////////////////////////////////////////////////
// Filename:    FormViewer.CC                                                //
// Written for: dBASE (32-bit versions)                                      //
// Written by:  Jim Sare - dBASE Inc. R&D Group                              //
// Copyright:   Copyright © dBASE Inc. 2002                                  //
// Run From:    :FormControls:FormViewer.CC                                  //
// Purpose:     To display a form within a form for view-only purposes.      //
// Usage:       Place a FormViewer on a form in the Form Designer.           //
//              Use the methods at runtime to display or close a form.       //
// Properties:                                                               //
//    Name:       errorCode                                                  //
//    Purpose:    Indicates reason for failure if an error occurs while a    //
//                form is being displayed. See the display method comments   //
//                for further information.                                   //
//                                                                           //
//    Name:       exceptionObject                                            //
//    Purpose:    Holds an object reference to an exception object which may //
//                contain detailed error information if an exception is      //
//                thrown while attempting to load and display a form. See    //
//                the display method comments for further information.       //
//                                                                           //
//    Name:       version                                                    //
//    Purpose:    Indicates release version of the FormViewer class.         //
// Methods:                                                                  //
//    Name:       display                                                    //
//    Purpose:    Displays a form for viewing.                               //
//    Parameters:                                                            //
//       cFilename - Filename (CFM/WFM) containing the form class to view.   //
//    Returns:    True if form load and open was successful, False if load   //
//                and open was not successful. If false is returned, the     //
//                errorCode property indicates the reason for the failure.   //
//                See the source code to determine reasons. Also the         //
//                exceptionObject property member will contain the exception //
//                object thrown (if any) when the error occurred. The        //
//                exception object may contain more detailed information     //
//                regarding the error.                                       //
//                                                                           //
//    Name:       closeCurrentForm                                           //
//    Purpose:    Close the currently displayed form (if any).               //
//    Parameters: None                                                       //
//    Returns:    True if close was successful, False if it was not.         //
///////////////////////////////////////////////////////////////////////////////
// Versioning and History comments:
// #define FORMVIEWER_VERSION  "1000"  // 04/12/2002 - Original version.
//#define FORMVIEWER_VERSION  "1001"  // 04/19/2002 - Added tlCannotView
#define FORMVIEWER_VERSION  "1002"  // 10/26/2002 - Corrected assignment of version
                                    //              property to FORMVIEWER_VERSION

CLASS FormViewer(o, n) of Container(o, n) custom

   if type("dB_SetParent") # "FP"
      extern chandle dB_SetParent(chandle, chandle) user32;
                from "SetParent"
   endIf

   new TextLabel(this, "tlCannotView")
   with (this.tlCannotView)
      alignHorizontal = 1  // Center
      visible = false
      height = 22
      left = 0
      top = 5
      width = 210
      text = "Unable To View File"
      colorNormal = "b/BtnFace"
      fontBold = true
   endwith

   // Set stock property members
   this.borderStyle :=      4                   // Single
   this.enabled :=          false               // Ensure that viewed form cannot be
                                                //   activated through mouse clicks, etc.

   // Set published custom property members
   this.errorCode =         0                   // Reason for a failure
   this.exceptionObject =   null                // Filled with exception object for
                                                //   detailed error information.
   this.version =           FORMVIEWER_VERSION  // Release version number.

   // Set PROTECTed custom property members
   this.filename =          ""
   this.viewForm =          null

   PROTECT filename, viewForm, makeInactive

   FUNCTION display(cFilename)  // Loads form file and displays form.
      PRIVATE cCls, f
      LOCAL oFile, cIn

      this.tlCannotView.visible := false
      this.tlCannotView.width := this.width
      this.errorCode := 0
      this.exceptionObject := new exception()
      // Check the filename and process it.
      if empty(cFilename) or (not file(cFilename))
         this.errorCode := 1   // No filename passed or file does not exist.
         this.tlCannotView.visible := true
         RETURN false
      endIf
      cCls = ""
      oFile = new File()
      try  // Attempt to read source file and parse for className.
         oFile.open(cFilename, "R")
         do while not oFile.eof()
            cIn = upper(lTrim(oFile.gets()))
            if at("CLASS ", cIn) = 1
               cCls = subStr(cIn, at(" ", cIn) + 1)       // Trim CLASS keyword.
               cCls = subStr(cCls, 1, at(" ", cCls) - 1)  // Trim everything after className.
               exit
            endIf
         endDo
         oFile.close()
      catch(exception e)
         this.exceptionObject := e
         this.errorCode := 2  // Error occurred while processing file.
         this.tlCannotView.visible := true
         RETURN false
      endTry
      if empty(cCls)
         this.errorCode := 3  // File does not appear to contain a CLASS statement.
         this.tlCannotView.visible := true
         RETURN false
      endIf
      // Attempt to load source file, instantiate the form, and initialize the
      //   form object for viewing.
      try
         set procedure to (cFilename) Additive
         this.filename := cFilename
         f = new &cCls.()
         f.left := 0
         f.top := 0
         f.height := f.height + 1
         f.menuFile := ""
         f.text := ""
         f.windowState := 0
         f.MDI := false
         f.autoCenter := false
         f.maximize := false
         f.minimize := false
         f.moveable := false
         f.sizeable := false
         f.sysmenu := false
         f.topMost := false
         f.visible := false
         f.enabled := false
         this.makeInactive(f)
      catch(exception e)
         this.exceptionObject := e
         this.errorCode := 4  // An error occurred while instantiating or
                              //   initializing the form.
         this.tlCannotView.visible := true
         RETURN false
      endTry
      try  // Attempt to open the form.
         f.open()
      catch(exception e)
         this.exceptionObject := e
         this.errorCode := 5  // An error occurred while attempting to open
                              //   the form.
         try  // Form failed to open correctly, so attempt to close it to
              //   cleanup and recover.
            f.close()
         catch(exception e)
            // Eat any errors that might occur when form is closed here
            // because we're just attempting to cleanup after bad form opening.
         endTry
         this.tlCannotView.visible := true
         RETURN false
      endTry
      dB_SetParent(f.hWND, this.hWND)  // Make this Container object the parent
                                       //   object of the form so that the form
                                       //   is displayed withing the Container
                                       //   boundaries.
      f.visible := true
      this.viewForm = f
      RETURN true

   PROCEDURE makeInactive
        // PROTECTed method to fully disable the form object and all contained
        //   objects. This method is recursive (it calls itself) to disable
        //   objects nested in SubForms, Containers, NoteBooks, etc.
      PARAMETERS o  // Must receive in PARAMETERS for PRIVATE scope.
      PRIVATE oRef

      if "|" + o.baseClassName + "|" $ "|FORM|SUBFORM|"
         o.open := iIf(o.baseClassName == "FORM", FORM::Open, SUBFORM::Open)
         o.close := iIf(o.baseClassName == "FORM", FORM::Close, SUBFORM::Close)
         o.onOpen := null
         o.onGotFocus := null
         o.onLostFocus := null
         o.onMove := null
         o.onSize := null
         o.canClose := null
         o.onClose := null
      endIf
      if not empty(o.first)
         oRef = o.first
         do
            oRef.onOpen = null
            oRef.onGotFocus = null
            oRef.onLostFocus = null
            if (type("oRef.first") == "O") and (not empty(oRef.first))
               this.makeInactive(oRef) // Recursive call to disable contained objects.
            endIf
            oRef := oRef.before
         until oRef.name == o.first.name
      endIf

   FUNCTION CloseCurrentForm
      // Closes currently displayed form (if any) and unloads the procedure file.
      PRIVATE f
      LOCAL lRet

      // If a form is already being viewed, close it.
      lRet = true
      f = this.viewForm
      this.viewForm = null
      if (type("f") == "O") and (not empty(f))
         try
            f.close()
            lRet = true
         catch(exception e)
            lRet = false
         endTry
      endIf
      // Close an open procedure file (.CFM/.WFM) if it was opened previously.
      f = this.filename
      this.filename := ""
      if (type("f") == "C") and (not empty(f))
         try
            close procedure (f)
         catch(exception e)
            // Eat any errors that might occur when procfile is closed.
         endTry
      endIf
      RETURN lRet

ENDCLASS  // FormViewer of Container

