Passing more infos into PopupMenu list functions
thomas_braun
I have a GUI with a SetVariable and a PopupMenu. The function providing the popup menu entries would need to read another GUI control for doing its job. As that is not possible, I now always have to reset the function defining the string for the popup menu.
Example:
Function/S GetList(string searchString)
return GrepList("abcd;efgh", searchString)
End
FUnction Test()
NewPanel/K=1
SetVariable searchstring, value = _STR:".*",proc=SetVarProc
PopupMenu pop, value=#"GetList(\".*\")"
End
Function SetVarProc(sva) : SetVariableControl
STRUCT WMSetVariableAction &sva
switch (sva.eventCode)
case 1: // mouse up
case 2: // Enter key
case 3: // Live update
PopupMenu pop, value=#("GetList(\"" + sva.sval + "\")")
break
endswitch
return 0
End
return GrepList("abcd;efgh", searchString)
End
FUnction Test()
NewPanel/K=1
SetVariable searchstring, value = _STR:".*",proc=SetVarProc
PopupMenu pop, value=#"GetList(\".*\")"
End
Function SetVarProc(sva) : SetVariableControl
STRUCT WMSetVariableAction &sva
switch (sva.eventCode)
case 1: // mouse up
case 2: // Enter key
case 3: // Live update
PopupMenu pop, value=#("GetList(\"" + sva.sval + "\")")
break
endswitch
return 0
End
Now I would prefer if the GetList function would be passed a struct similiar to WMSetVariableAction so that it could dynamically generate the list itself. This new struct should have at least a window name and control name member.
My current approach makes the code quite complicated, and also took a non-trivial amount of time to get the quoting in the popupmenu value string right ;)
If you want a function that specifically resets popupmenu lists based on setvariable actions, why not write a function that takes WMSetVariableAction as a parameter? Or are you looking for something more general?
I find getting and setting control values to be laborious in Igor. I often wish Igor had JavaScript-like window objects so that I could write something like PanelName.PopUpName.value = PanelName.SetvarName.value. Sometimes I create a structure for a panel with a substructure for each control that can be populated using a wrapper for ControlInfo like this:
int16 type
string ctrlName
variable value
string sval
STRUCT RGBColor rgb
STRUCT RGBAColor rgba
variable selcol
endstructure
static function getControlValue(string win, string controlName, STRUCT ControlValueStructure &s)
ControlInfo /W=$win $controlName
s.ctrlName = controlName
s.type = v_flag
switch (abs(V_Flag))
case 3: // popup menu
s.rgb.red = V_Red; s.rgb.green = V_Green; s.rgb.blue = V_Blue
s.rgba.red = V_Red; s.rgba.green = V_Green; s.rgba.blue = V_Blue
s.rgba.alpha = V_Alpha
case 2: // checkbox
case 4: // valdisplay
case 5: // SetVariable
case 7: // slider
case 8: // tab
s.value = v_value
s.sval = s_value
break
case 11: // listbox
s.value = v_value
s.sval = s_value
s.selcol = v_selcol
break
endswitch
end
An equivalent SetControlValue() function could be useful. Then I could use ModifyControl and SetControlValue as control-type agnostic functions.
July 22, 2021 at 01:14 am - Permalink
> If you want a function that specifically resets popupmenu lists based on setvariable actions, why not write a function that takes WMSetVariableAction as a parameter? Or are you looking for something more general?
Because I still would need to manually reset the value string. And I want to avoid that as it is difficult to maintain.
July 22, 2021 at 01:33 am - Permalink
Your GetList function could use ControlInfo to find the value of searchstring.
I often have two popup menus when I need the user to select a wave. One to select the datafolder to look in and one with all the waves in that datafolder. To do that the wave-selection popmenu function uses ControlInfo to find the value of the datafolder popupmenu.
I still have to update the wave-selection popup menu whenever the datafolder value is changed, just as you do with your popup call when searchstring is called, but I can get away with a simple "PopupMenu DisplayedWavePopUp mode=1, win=$PU_Struct.win" without having to change the value string every time.
July 22, 2021 at 02:51 am - Permalink
> Your GetList function could use ControlInfo to find the value of searchstring.
I don't think this will work. The name of the window is not fixed. And I also can't rely on the top window being the one holding the control as the GUI control could be called programmatically.
July 22, 2021 at 03:19 am - Permalink
Also (Thomas has probably already thought about this, but it's worth noting here):
If you feed a user-supplied regex to grep or greplist, you need to consider what happens in the event of a regex error.
try..catch..endtry is one way to deal with runtime errors.
July 22, 2021 at 04:48 am - Permalink
In reply to > Your GetList function… by thomas_braun
Use a global string?
... I'll get my coat.
July 22, 2021 at 04:55 am - Permalink
If both controls are in the same window you use $PU_Struct.win as the window name. Otherwise you will have to pass the name through the PopupMenu value=#"GetList(\".*\")" call, as a parameter for GetList.
EDIT
I guess the window name of the control cannot be accessed inside of GetList so you will have to pass it along through the value=#GetList call
July 22, 2021 at 07:05 am - Permalink
value=#("EccentricXPS#XPSViewPopUpWaveList(2, \""+SubWindow+"\", \"DataFolderPopUp\")")
This is a quick copy-and-paste from one of my programs. It passes the window name (the variable SubWindow) along as well as the name of the control (the string value "DataFolderPopUp") to run ControlInfo on
July 22, 2021 at 07:13 am - Permalink
Just to clarify: I do have a solution which works already. I just think it is too complicated to use and would like to have a more straightforward solution.
> Use a global string?
Multiple windows with multiple controls. So nope.
July 22, 2021 at 08:55 am - Permalink
> If you feed a user-supplied regex to grep or greplist, you need to consider what happens in the event of a regex error.
> try..catch..endtry is one way to deal with runtime errors.
Yes, good code does that. Mine here is a MWE.
July 22, 2021 at 08:56 am - Permalink
In reply to value=#("EccentricXPS… by olelytken
olelytken's solution works, no? you must know the host window name and the corresponding setvar when you create the popup, so just hardwire the names into the GetList function call and run ControlInfo from GetList?
July 22, 2021 at 09:11 am - Permalink
> olelytken's solution works, no? you must know the host window name and the corresponding setvar when you create the popup, so just hardwire the names into the GetList function call and run ControlInfo from GetList?
Yes it works in principle. But unfortunately in my case the window name is getting renamed occasionally. (Yes this was a dump thing to do in the first place, but that is how it is.)
July 23, 2021 at 02:28 am - Permalink