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.