!**************************************************************************************************!
! author : JPH
!
! purpose: test the GCONTROL /MON switch
! 
! NOTE: legacy behavior (pre 2.7.2) was very different:
!  * MENU, BUTTON and CHOICE monitoring was limited to the item number (no string values)
!  * In 2.7.2, a different MNEMONIC for action changes versus result monitor changes was added
!  * Did not get action change messages for MENU,CHOICE,BUTTON with /EDIT=F
!
!  For these reasons, the tests are broken into legacy and post 2.7.1 tests
!**************************************************************************************************!
startmacro
  switch INTERACTIVE interAct GET DEF=TRUE  SDEF=TRUE  ! for normal interactive test(s)
  switch NOTIMER     noTimer  GET DEF=FALSE SDEF=TRUE
  switch HEADLESS    headless GET DEF=FALSE SDEF=TRUE
  invoke newVer nxm.sys.lib.StringUtil.compareVersions("^env.nmversion","2.7.1")
  if newVer > 0 then
    res valTab {}
    res D:valTab.dval1 1.0
    res L:valTab.fval1 1.0
    res L:valTab.lval1 1
    res D:valTab.tval1 1
    res S:valTab.prompt1 "Initial"
    res S:valTab.button1 "Initial"
    res S:valTab.button2 "Initial"
    res S:valTab.menu1   "Initial"
    res S:valTab.choice1 "Initial"
 
    res L:numValTabMsgs 0
    calc L:expectedNumValTabMsgs valTab.getSize 2 * ! 1 for external and 1 for simulated click (action)
    invoke changed_by_user_input nxm.sys.libg.GValue.changed_by_user_input
    invoke changed_by_poll nxm.sys.libg.GValue.changed_by_poll
    invoke changed_by_msg  nxm.sys.libg.GValue.changed_by_msg

    invoke shellHeadless nxm.sys.lib.Shell.isHeadless()
    if interAct OR headless OR shellHeadless then
      pipe on

      panel/msgid=MAIN/setup/controls=gc

        gcontrol label  MACRO "MACRO"
        gcontrol menu main "Exit with Status = " "PASS,FAIL" /tleft
        set gc.main.itemcolors {PASS=GREEN,FAIL=RED}

        gcontrol choice changeType "Change by: " "Result,Click" "Result"
        gcontrol label  xvalmonitorsLab "xVAL Monitors"
          set instructions "This test should run to completion and close.  If you have to click to close it it failed."
          gcontrol TEXT instructText instructions "^instructions" 24 3 /title

          set gc.valTab {}
          gcontrol DVAL valTab.dval1 "DVAL1" DEF=1 MIN=0 MAX=-1 INC=0.001 /mon=valTab.dval1 /edit=f
          gcontrol FVAL valTab.fval1 "FVAL1" DEF=1 MIN=0 MAX=-1 INC=0.001 /mon=valTab.fval1 /edit=f
          gcontrol LVAL valTab.lval1 "LVAL1" DEF=1 MIN=0 MAX=-1 INC=0.001 /mon=valTab.lval1 /edit=f
          gcontrol TVAL valTab.tval1 "TVAL1" DEF=1 MIN=0 MAX=-1 INC=0.001 /mon=valTab.tval1 /edit=f

        gcontrol label  otherMonitorsLab "Other Monitors"
          gcontrol prompt valTab.prompt1 "PROMPT(SVAL)   "    DEF=valTab.prompt1          /mon=valTab.prompt1                /edit=f
          gcontrol button valTab.button1 "BUTTON1        " "Action,External,Initial" valTab.button1 /mon=valTab.button1  /tleft        /edit=f
          gcontrol button valTab.button2 "BUTTON2 - Index" "Action,External,Initial" valTab.button2 /mon=valTab.button2  /tleft        /edit=f
          gcontrol menu   valTab.menu1   "MENU1          " "Action,External,Initial" valTab.menu1   /mon=valTab.menu1    /tleft /nc=3  /edit=f
          gcontrol choice valTab.choice1 "CHOICE1        " "Action,External,Initial" valTab.choice1 /mon=valTab.choice1                /edit=f

      gcontrol label  testsLab "Tests"
        gcontrol button EXTERNALCHANGE  "" "EXTERNAL_CHANGE"
        gcontrol button ACTIONCHANGE    "" "ACTION_CHANGE"
        if noTimer isFALSE then set this.timer(0) 2
      pipe off
    endif
  else
    call test_legacy
  endif
endmacro

!**************************************************************************************************!
procedure processMessage m:msg

!say "^reg.main.name: msg ^msg"
  if newVer > 0 then
    if msg.name eqs "MAIN" or msg.name EQS "CLOSE" then
      assert/text="^reg.main.name: number valTab. msgs ^numValTabMsgs = ^expectedNumValTabMsgs expected?" &
                  expectedNumValTabMsgs EQ numValTabMsgs
      pipe stop


    elseif msg.name EQS "TIMER" then
      if eventNum NREXISTS then
        res L:eventNum 1
      else
        calc L:eventNum eventNum 1 +
      endif
      if eventNum EQ 1 then
        message FUNC=SEND ID=MAIN NAME="EXTERNALCHANGE"
        set this.timer(0) -2
      elseif eventNum EQ 2 then
        message FUNC=SEND ID=MAIN NAME="ACTIONCHANGE"
        set this.timer(0) -2
      else
        message FUNC=SEND ID=MAIN NAME="CLOSE"
      endif

    elseif msg.name eqs "EXTERNALCHANGE"  then
        set CHANGE_TYPE "EXTERNAL"
        set expected_info_xval   ^changed_by_poll
        set expected_info_prompt ^changed_by_poll
        set expected_info_menu 2
        res d:valTab.dval1 2
        res f:valTab.fval1 2
        res L:valTab.lval1 2
        res D:valTab.tval1 2
        res S:valTab.prompt1 "Result Change"
        res S:valTab.button1 "External"
        res S:valTab.button2 "External"
        res S:valTab.menu1   "External"
        res S:valTab.choice1 "External"
 
    elseif msg.name eqs "ACTIONCHANGE"  then
        set CHANGE_TYPE "ACTION"
        set expected_info_xval   ^changed_by_msg
        set expected_info_prompt ^changed_by_msg
        set expected_info_menu 1
        res gc.valTab.dval1.action 1
        res gc.valTab.fval1.action 1
        res gc.valTab.lval1.action 1
        res gc.valTab.tval1.action 1
        set gc.valTab.prompt1.action "Click change"
        res gc.valTab.button1.action "Action"
        res gc.valTab.button2.action "Action"
        res gc.valTab.menu1.action   "Action"
        res gc.valTab.choice1.action "Action"

    elseif msg.name eqss "VALTAB."  then
      sedit "^msg.name" shortID "SUBS" "VALTAB." ""
      if numValTabMsgs NREXISTS then
        res L:numValTabMsgs 0
      endif
      calc L:numValTabMsgs numValTabMsgs+1

      if shortID eqs "DVAL1" or shortID eqs "LVAL1" or shortID eqs "FVAL1" or shortID eqs "TVAL1" then
        assert/text="Change type=^CHANGE_TYPE: ^shortID:  expected info=^expected_info_xval, got info=^msg.info" expected_info_xval EQ msg.info
        if CHANGE_TYPE EQS "EXTERNAL" then
          assert/text="Change type=^CHANGE_TYPE: ^shortID: result change value=^msg.data" msg.data EQ 2
        else
          assert/text="Change type=^CHANGE_TYPE: ^shortID: click change value=^msg.data" msg.data EQ 1
        endif

      elseif shortID eqs "BUTTON1" or shortID eqs "BUTTON2" or shortID eqs "MENU1" or shortID eqs "CHOICE1" then
        assert/text="Change type=^CHANGE_TYPE: ^shortID:  expected info=^expected_info_menu, got info=^msg.info" expected_info_menu EQ msg.info
        if CHANGE_TYPE EQS "EXTERNAL" then
          assert/text="Change type=^CHANGE_TYPE: ^shortID: result change value=^msg.data" "^msg.data" EQS "External"
        else
          assert/text="Change type=^CHANGE_TYPE: ^shortID: click change value=^msg.data" "^msg.data" EQS "Action"
        endif

      elseif shortID eqs "PROMPT1"  then
        assert/text="Change type=^CHANGE_TYPE: ^shortID:  expected info=^expected_info_prompt, got info=^msg.info" expected_info_prompt EQ msg.info
        if CHANGE_TYPE EQS "EXTERNAL" then
          assert/text="Change type=^CHANGE_TYPE: ^shortID: msg.data='^msg.data'" "^msg.data" EQS "Result Change"
        else
          assert/text="Change type=^CHANGE_TYPE: ^shortID: msg.data='^msg.data'" "^msg.data" EQS "Click Change"
        endif
      else
        assert/text="Change type=^CHANGE_TYPE: ^shortID - unexpected message ^msg" false
        message FUNC=SEND ID=MAIN NAME="CLOSE"
      endif

    else
      ! do nothing
      say "^reg.main.name: unhandled message ^msg"
    endif
  else

    call processMessage_legacy
  
  endif
return


procedure processMessage_legacy

  if msg.name eqs "MAIN" or msg.name EQS "CLOSE" then
    assert/text="^reg.main.name: number valTab. msgs ^numValTabMsgs = ^expectedNumValTabMsgs expected?" &
                expectedNumValTabMsgs EQ numValTabMsgs
    pipe stop


  elseif msg.name EQS "TIMER" then
    if eventNum NREXISTS then
      res L:eventNum 1
    else
      calc L:eventNum eventNum 1 +
    endif
    if eventNum EQ 1 then
      message FUNC=SEND ID=MAIN NAME="EXTERNALCHANGE"
      set this.timer(0) -2
    elseif eventNum EQ 2 then
      message FUNC=SEND ID=MAIN NAME="ACTIONCHANGE"
      set this.timer(0) -2
    else
      message FUNC=SEND ID=MAIN NAME="CLOSE"
    endif

  elseif msg.name eqs "EXTERNALCHANGE"  then
      set CHANGE_TYPE "EXTERNAL"
      set expected_info_xval ^changed_by_poll
      set expected_info_prompt 0
      set expected_info_menu 2
      res d:valTab.dval1 2
      res f:valTab.fval1 2
      res L:valTab.lval1 2
      res D:valTab.tval1 2
      res S:valTab.prompt1 "Result Change"
      res S:valTab.button1 2 !"B2"
      res S:valTab.button2 2
      res S:valTab.menu1   2 !"B2"
      res S:valTab.choice1 2 !"B2"
 
  elseif msg.name eqs "ACTIONCHANGE"  then
      set CHANGE_TYPE "ACTION"
      set expected_info_xval ^changed_by_click
      set expected_info_prompt 0
      ! This does not change from what is is currently
      if expected_info_menu NREXISTS then
        set expected_info_menu 3
      endif
      res gc.valTab.dval1.action 1
      res gc.valTab.fval1.action 1
      res gc.valTab.lval1.action 1
      res gc.valTab.tval1.action 1
      set gc.valTab.prompt1.action "Click change"      
      res gc.valTab.button1.action "^gc.button1.value"
      res gc.valTab.button2.action "^gc.button2.value"
      res gc.valTab.menu1.action   "^gc.menu1.value"
      res gc.valTab.choice1.action "^gc.choice1.value"

  elseif msg.name eqss "VALTAB."  then
    sedit "^msg.name" shortID "SUBS" "VALTAB." ""
    if numValTabMsgs NREXISTS then
      res L:numValTabMsgs 0
    endif
    calc L:numValTabMsgs numValTabMsgs+1

    if shortID eqs "DVAL1" or shortID eqs "LVAL1" or shortID eqs "FVAL1" or shortID eqs "TVAL1" then
      assert/text="Change type=^CHANGE_TYPE: ^shortID:  expected info=^expected_info_xval, got info=^msg.info" expected_info_xval EQ msg.info
      if CHANGE_TYPE EQS "EXTERNAL" then
        assert/text="Change type=^CHANGE_TYPE: ^shortID: result change value=^msg.data" msg.data EQ 2
      else
        assert/text="Change type=^CHANGE_TYPE: ^shortID: click change value=^msg.data" msg.data EQ 1
      endif

    elseif shortID eqs "BUTTON1" or shortID eqs "BUTTON2" or shortID eqs "MENU1" or shortID eqs "CHOICE1" then
      assert/text="Change type=^CHANGE_TYPE: ^shortID:  expected info=^expected_info_menu, got info=^msg.info" expected_info_menu EQ msg.info
      if CHANGE_TYPE EQS "EXTERNAL" then
        assert/text="Change type=^CHANGE_TYPE: ^shortID: result change value=^msg.data" "^msg.data" EQS "B2"
      else
        assert/text="Change type=^CHANGE_TYPE: ^shortID: click change value=^msg.data" "^msg.data" EQS "INITIAL"
      endif

    elseif shortID eqs "PROMPT1"  then
      assert/text="Change type=^CHANGE_TYPE: ^shortID:  expected info=^expected_info_prompt, got info=^msg.info" expected_info_prompt EQ msg.info
      if CHANGE_TYPE EQS "EXTERNAL" then
        assert/text="Change type=^CHANGE_TYPE: ^shortID: msg.data='^msg.data'" "^msg.data" EQS "Result Change"
      else
        assert/text="Change type=^CHANGE_TYPE: ^shortID: msg.data='^msg.data'" "^msg.data" EQS "Click Change"
      endif
    else
      assert/text="Change type=^CHANGE_TYPE: ^shortID - unexpected message ^msg" false
      message FUNC=SEND ID=MAIN NAME="CLOSE"
    endif

  else
    ! do nothing
    say "^reg.main.name: unhandled message ^msg"
  endif

return

procedure test_legacy

  res valTab {}
  res D:valTab.dval1 1.0
  res L:valTab.fval1 1.0
  res L:valTab.lval1 1
  res D:valTab.tval1 1
  res S:valTab.prompt1 3 !"Initial"
  res S:valTab.button1 3 !"Initial"
  res S:valTab.button2 3          ! Monitor the index (legacy behavior pre 2.7.1)
  res S:valTab.menu1   3 !"Initial"
  res S:valTab.choice1 3 !"Initial"
  
  res L:numValTabMsgs 0
  calc L:expectedNumValTabMsgs valTab.getSize 2 * ! 1 for external and 1 for simulated click (action) 
  calc L:expectedNumValTabMsgs expectedNumValTabMsgs-4 ! Do not get action change messages for MENU,CHOICE,BUTTON with /EDIT=F
  ! These values in the INFO field indicate a result /MON change difference from a click change
  invoke changed_by_click nxm.sys.libg.GValue.changed_by_click
  invoke changed_by_poll nxm.sys.libg.GValue.changed_by_poll

  if interAct then
    pipe on

    panel/msgid=MAIN/setup/controls=gc

      gcontrol label  MACRO "MACRO"
      gcontrol menu main "Exit with Status = " "PASS,FAIL" "PASS" /tleft
      set gc.main.itemcolors {PASS=GREEN,FAIL=RED}

      gcontrol choice changeType "Change by: " "Result,Click" "Result"
      gcontrol label  xvalmonitorsLab "xVAL Monitors"
        set instructions "This test should run to completion and close.  If you have to click to close it it failed."
        gcontrol TEXT instructText instructions "^instructions" 24 3 /title

        set gc.valTab {}
        gcontrol DVAL valTab.dval1 "DVAL1" DEF=1 MIN=0 MAX=-1 INC=0.001 /mon=valTab.dval1 /edit=f
        gcontrol FVAL valTab.fval1 "FVAL1" DEF=1 MIN=0 MAX=-1 INC=0.001 /mon=valTab.fval1 /edit=f       
        gcontrol LVAL valTab.lval1 "LVAL1" DEF=1 MIN=0 MAX=-1 INC=0.001 /mon=valTab.lval1 /edit=f
        gcontrol TVAL valTab.tval1 "TVAL1" DEF=1 MIN=0 MAX=-1 INC=0.001 /mon=valTab.tval1 /edit=f

      gcontrol label  otherMonitorsLab "Other Monitors"
        gcontrol prompt valTab.prompt1 "PROMPT(SVAL)   "    DEF=valTab.prompt1          /mon=valTab.prompt1                /edit=f
        gcontrol button valTab.button1 "BUTTON1        " "B1,B2,Initial" valTab.button1 /mon=valTab.button1  /tleft        /edit=f
        gcontrol button valTab.button2 "BUTTON2 - Index" "B1,B2,Initial" valTab.button2 /mon=valTab.button2  /tleft        /edit=f
        gcontrol menu   valTab.menu1   "MENU1          " "B1,B2,Initial" valTab.menu1   /mon=valTab.menu1    /tleft /nc=3  /edit=f
        gcontrol choice valTab.choice1 "CHOICE1        " "B1,B2,Initial" valTab.choice1 /mon=valTab.choice1                /edit=f

    gcontrol label  testsLab "Tests"
      gcontrol button EXTERNALCHANGE  "" "EXTERNAL_CHANGE"
      gcontrol button ACTIONCHANGE    "" "ACTION_CHANGE"
      if /NOTIMER isFALSE then
        set this.timer(0) 2
      endif
    pipe off
  endif
return
