Dynamic PopupMenus in panels with subwindows

Dear Igorians,

I have several popupmenus in multiple subwindows of a panel.

For some of the popupmenus I need a dynamic display of contents so that the list is populated depending on other controls within that panel. For that, I have defined the value of those popupmenus as a function that returns a list depending on choices made by the users on other controls within the same panel. That function I call here "FuncSelectList" (e.g. PopupMenu Dynamic_PU, title="Select Something", value=FuncSelectList()).

I would like now to generate/pass awareness of which panel was clicked when I click on one of these dynamic popupmenus. My problem is that the moment that a dynamic PopupMenu is clicked, FuncSelectList() is called and I do not see how I can generate/pass subwindow awareness within that function. For a Proc() I would use an inbuilt structure in order to access the WIN variable, such as :
Function Proc_SelectData(PU_Struct) : PopupMenuControl
    STRUCT WMPopupAction &PU_Struct
   
    String sWin = PU_Struct.win
    SetActiveSubwindow $sWin
    //some more code goes here
End


Is there a way I could take advantage of a structure within FuncSelectList() so that I can access the WIN variable? Or is there any other way I can raise window awareness within FuncSelectList()?

Thanks in advance,
R.
You can include a string in the function call with the name of the window. The example below calls the function EccentricXPS#XPSViewPopUpWaveList(2, SubWindow, DataFolderPopUp) every time the popup menu is clicked. Keep in mind that in your example the popup menu list is only generated once when the menu is created (if I remember correctly). To make the list dynamic you need the #("xxxxx"). There is a long description somewhere in the popup menu help.

PopupMenu DisplayedWavePopUp value=#("EccentricXPS#XPSViewPopUpWaveList(2, \""+SubWindow+"\", \"DataFolderPopUp\")")
Many thanks for the input Olelytken!

How you are actually defining your SubWindow variable? I think that is my main question.

Below is how I have implemented the dynamic aspect of the second  PopupMenu SelectSection whose value is defined by FuncSelectList1() using a Strswhich-Case-EndSwitch statement. For proper use, the user has to first make a selection on the left side PopupMenu (SelectData) which contains a simple list. Upon interaction with that popupmenu, the SubWindow number is passed to a global variable ActiveSubPanel which is recalled by FuncSelectList1() upon interaction with the dynamic PopupMenu SelectSection which then uses that to read the selection of the SelectData popupmenu of the same panel.

The problem of this approach is that correct functioning requires the user to first select the popupmenu on the left (PopupMenu SelectData) and then proceed to popupmenu on the right (PopupMenu SelectSection). I would like for the subwindow to be detected and that being passed to the value of PopupMenu SelectSection

Function Panel_DisplayResults1()
    NewPanel /W=(0,0,1200,400) /N=ResultsPanel1 /K=1
    //Define Vertical guides
    DefineGuide UGV0={FL,200},UGV1={UGV0,0.33333333,FR},UGV2={UGV0,0.66666666, FR}
    //Define Horizonzal guides
    DefineGuide UGH0={FB,0.5,FT}
   
    Variable /G ActiveSubPanel
    ActiveSubPanel = 0 
    string quote = "\""
    String DataTypeList = quote + "A;B;C;D;E;F;G;" + quote
    String sSubPanelName
    Variable /G PlotCase = 1
    //Create subpanels/subwindows where data will be displayed according to user input on controls
    Variable i
    for(i = 0; i < 2; i += 1)
        switch(i)
            case 0:
                NewPanel/FG=(UGV0,FT,UGV1,UGH0) /HOST=ResultsPanel1
                break
            case 1:
                NewPanel/FG=(UGV1,FT,UGV2,UGH0) /HOST=ResultsPanel1
                break
        endswitch
        sSubPanelName = "P" + num2istr(i)
        RenameWindow #,$sSubPanelName //Each subwindow has a name

        //Indicate controls needed
                       
        PopupMenu SelectData, title="Data Type", mode=1, bodyWidth=110, value=#DataTypeList, pos={125,10},Proc=Proc_SelectData1    
        PopupMenu SelectSection, title="Section", mode=1, bodyWidth=100, value=FuncSelectList1(), pos={265,10}
       
        // add more controls here...
 
        SetActiveSubwindow ## //Go back to parent window
    endfor
End

//---------------------------------------------------------------------------------------------------------------

Function/S FuncSelectList1()

    //take the number of the active subwindow from the global variable
    NVAR ActiveSubPanel
    String /G Path2SubPanel = "#P"+num2str(ActiveSubPanel)
    Print "Path2Subpanel is:"+Path2SubPanel
   
    //Use the active subwindow path to extract info (S_value) on the other popupbox
    SetActiveSubwindow $Path2SubPanel
    ControlInfo SelectData
   
    String SectionList
    Strswitch(S_Value)
        Case "A":
        Case "B":
            SectionList = "First;Second;Third;Fourth;"
            break
   
        Case "C":  
        Case "D":
            SectionList = "Primeiro;Segundo;Terceiro;Quarto;"
            break

        Case "E":
        Case "F":
        Case "G":
            SectionList = "Erste; Zweite; Dritte; Vierte;"
            break
   
    EndSwitch
    SetActiveSubWindow ## //return to host window
    return SectionList
End

//---------------------------------------------------------------------------------------------------------------

Function Proc_SelectData1(PU_Struct) : PopupMenuControl
    STRUCT WMPopupAction &PU_Struct
   
    String sWin = PU_Struct.win
    SetActiveSubwindow $sWin //This activates the subpanel where controls were selected
   
    //extract the subwindow number from the panel name
    String sSubPanelNumber
    SplitString/E=("#P([[:digit:]]+)") sWin, sSubPanelNumber
    print sSubPanelNumber + "eheheh"
    Variable vSubPanelNumber = str2num(sSubPanelNumber)
       
    //pass the number of the active subwindow onto a global variable
    NVAR ActiveSubPanel
    ActiveSubPanel = vSubPanelNumber
   
    if(PU_Struct.eventCode == 2) // mouse up
        //some come for proc   
        Return 0
    Else
        Return 0
   
    EndIf
   
    SetActiveSubwindow ##   //return to host window
End

I've not tried to tidy it up, but the following appears to work (without using the global):
Function Panel_DisplayResults1()
    NewPanel /W=(0,0,1200,400) /N=ResultsPanel1 /K=1
    //Define Vertical guides
    DefineGuide UGV0={FL,200},UGV1={UGV0,0.33333333,FR},UGV2={UGV0,0.66666666, FR}
    //Define Horizonzal guides
    DefineGuide UGH0={FB,0.5,FT}
 
    string quote = "\""
    String DataTypeList = quote + "A;B;C;D;E;F;G;" + quote
    String sSubPanelName
    Variable /G PlotCase = 1
    //Create subpanels/subwindows where data will be displayed according to user input on controls
    Variable i
    for(i = 0; i < 2; i += 1)
        switch(i)
            case 0:
                NewPanel/FG=(UGV0,FT,UGV1,UGH0) /HOST=ResultsPanel1
                break
            case 1:
                NewPanel/FG=(UGV1,FT,UGV2,UGH0) /HOST=ResultsPanel1
                break
        endswitch
        sSubPanelName = "P" + num2istr(i)
        RenameWindow #,$sSubPanelName //Each subwindow has a name
       
 
        //Indicate controls needed
 
        PopupMenu SelectData, title="Data Type", mode=1, bodyWidth=110, value=#DataTypeList, pos={125,10},Proc=Proc_SelectData1    
        PopupMenu SelectSection, title="Section", mode=1, bodyWidth=100, value=#("FuncSelectList1(\""+WinName(0, 64) + "#" + sSubPanelName+"\")"), pos={265,10}
 
        // add more controls here...
 
        SetActiveSubwindow ## //Go back to parent window
    endfor
End
 
//---------------------------------------------------------------------------------------------------------------
 
Function/S FuncSelectList1(sSubWinName)
    String sSubWinName
 
    Print "Path2Subpanel is:"+sSubWinName
 
    ControlInfo/W=$sSubWinName SelectData
 
    String SectionList
    Strswitch(S_Value)
        Case "A":
        Case "B":
            SectionList = "First;Second;Third;Fourth;"
            break
 
        Case "C":  
        Case "D":
            SectionList = "Primeiro;Segundo;Terceiro;Quarto;"
            break
 
        Case "E":
        Case "F":
        Case "G":
            SectionList = "Erste; Zweite; Dritte; Vierte;"
            break
 
    EndSwitch
    return SectionList
End
 
//---------------------------------------------------------------------------------------------------------------
 
Function Proc_SelectData1(PU_Struct) : PopupMenuControl
    STRUCT WMPopupAction &PU_Struct
 
    String sWin = PU_Struct.win
    SetActiveSubwindow $sWin //This activates the subpanel where controls were selected
 
    //extract the subwindow number from the panel name
    String sSubPanelNumber
    SplitString/E=("#P([[:digit:]]+)") sWin, sSubPanelNumber
    print sSubPanelNumber + "eheheh"
    Variable vSubPanelNumber = str2num(sSubPanelNumber)
 
    //pass the number of the active subwindow onto a global variable
    NVAR ActiveSubPanel
    ActiveSubPanel = vSubPanelNumber
 
    if(PU_Struct.eventCode == 2) // mouse up
        //some come for proc   
        Return 0
    Else
        Return 0
 
    EndIf
 
    SetActiveSubwindow ##   //return to host window
End

Regards,
Kurt
Thank you Kurt, it seems to work well I will look further at what you wrote.

Quick question though: what might be the best approach to write this if for instance I would instead force the dynamic popupmenu to be populated upon interaction with the first (static) popupmenu, rather than, as I do now, for the list to be defined only upon user interaction with the dynamic popupmenu.

I'am actually quite happy that it works, but was wondering of how could be written differently.

Many thanks again!

Cheers,
R.
Try this. It will create four windows with two popup menus in each. You have to move the windows to see all four.

Function Test()
    Variable i=0
    String WindowName=""
    for (i=0; i<4; i+=1)
        Display/K=1
        WindowName=S_name
        PopUpMenu PopUpOne value="one;two;three;four;"
        PopUpMenu PopUpTwo value=#("PopUpValue(\""+WindowName+"\")")
    endfor
end

Function/S PopUpValue(WindowName)
String WindowName
    ControlInfo /W=$WindowName PopUpOne
    Return S_Value+" monkey;"+S_Value+" cat;"+S_Value+" dog;"+S_Value+" pig;"
end
Thank you Olelytken - this was helpful!

I see the commonalities between your example
 value=#("PopUpValue(\""+WindowName+"\")")
and Kurt's
 value=#("FuncSelectList1(\""+WinName(0, 64) + "#" + sSubPanelName+"\")")

Both of which are helpful in my case.

However, I was also wondering if it is possible to use the statitc PopUpMenu (PopUpOne) to dynamically push the value to be taken by the dynamic PopupMenu (PopUpTwo, in your case), in a way refreshing/updating that control, rather than having PopupTwo reading the status of PopOne only when interacted with. Any guesses if this possible at all?
rhjpires wrote:
Thank you Olelytken - this was helpful!

I see the commonalities between your example
 value=#("PopUpValue(\""+WindowName+"\")")
and Kurt's
 value=#("FuncSelectList1(\""+WinName(0, 64) + "#" + sSubPanelName+"\")")

Both of which are helpful in my case.

However, I was also wondering if it is possible to use the statitc PopUpMenu (PopUpOne) to dynamically push the value to be taken by the dynamic PopupMenu (PopUpTwo, in your case), in a way refreshing/updating that control, rather than having PopupTwo reading the status of PopOne only when interacted with. Any guesses if this possible at all?


Try this function (substitute it into the code I provided previously):
Function Proc_SelectData1(PU_Struct) : PopupMenuControl
    STRUCT WMPopupAction &PU_Struct
 
    String sWin = PU_Struct.win
 
    //extract the subwindow number from the panel name
    String sSubPanelNumber
    SplitString/E=("#P([[:digit:]]+)") sWin, sSubPanelNumber
    print sSubPanelNumber + "eheheh"
    Variable vSubPanelNumber = str2num(sSubPanelNumber)
 
    if(PU_Struct.eventCode == 2) // mouse up
        PopupMenu SelectSection, win=$sWin, mode=1
    Else
 
    EndIf
   
    return 0
End


Cheers,
Kurt
This is the other option where popup menu one affects popup menu two:

Function Test()
    Variable i=0
    for (i=0; i<4; i+=1)
        Display/K=1
        PopUpMenu PopUpOne value="one;two;three;four;", proc=PopUpProc
        PopUpMenu PopUpTwo value="one monkey;one cat;one dog;one pig;"
    endfor
end


Function PopUpProc(PU_Struct) : PopupMenuControl
Struct WMPopupAction &PU_Struct
    String ValueStr="\""+PU_Struct.popStr+" monkey;"+PU_Struct.popStr+" cat;"+PU_Struct.popStr+" dog;"+PU_Struct.popStr+" pig;\""
    PopUpMenu PopUpTwo mode=1, value=#ValueStr, win=$PU_Struct.win
end
One of my most common experiences in this forum is to be either bewildered or to "head-slap" myself - I now count one more for the latter. Amazing how one skips the obvious!

Cheers Kurt & Olelytken!

R.