
Accessing user-defined structures from controls (buttons, listbox...)

Nasser
I'd like to access the members of a structure which is selected from a ListBox (or a popup menu).
The challenge is that the event (e.g. Cell Selected) calls a procedure which can have only one parameter : the Control name, whereas I'd like to pass also a structure reference.
First, I tried to "encapsulate" the control into the structure, so that each instance of the structure has its own button (this button is aimed at changing the values of the structures data members) :
Structure class_VFA string str_Analyte variable RT variable Vc_Mono variable Vc_Dimer variable Sdev_RT variable Sdev_Vc_Mono variable Sdev_Vc_Dimer variable RTMin variable RTMax variable VcMin_Mono variable VcMax_Mono variable VcMin_Dimer variable VcMax_Dimer STRUCT WMButtonAction Button_RedefineCoords EndStructure //----------------------------------------------------------------------------- //Fonction d'Initialisation //------------------------------ Function Init_Analyte(str_Analyte,instance_locale,RT,Vc_Mono,Vc_Dimer,Sdev_RT,Sdev_Vc_Mono,Sdev_Vc_Dimer,RTMin,RTMax,VcMin_Mono,VcMax_Mono,VcMin_Dimer,VcMax_Dimer) string str_Analyte STRUCT class_VFA &instance_locale variable RT,Vc_Mono,Vc_Dimer,Sdev_RT,Sdev_Vc_Mono,Sdev_Vc_Dimer,RTMin,RTMax,VcMin_Mono,VcMax_Mono,VcMin_Dimer,VcMax_Dimer instance_locale.str_Analyte = str_Analyte instance_locale.RT = RT instance_locale.Vc_Mono = Vc_Mono instance_locale.Vc_Dimer = Vc_Dimer instance_locale.Sdev_RT = Sdev_RT instance_locale.Sdev_Vc_Mono = Sdev_Vc_Mono instance_locale.Sdev_Vc_Dimer = Sdev_Vc_Dimer instance_locale.RTMin = RTMin instance_locale.RTMax = RTMax instance_locale.VcMin_Mono = VcMin_Mono instance_locale.VcMax_Mono = VcMax_Mono instance_locale.VcMin_Dimer = VcMin_Dimer instance_locale.VcMax_Dimer = VcMax_Dimer instance_locale.Button_RedefineCoords.ctrlName = "Button_Coords_"+str_Analyte //------------------------------------------------------------------------------------------------------------------ Function Afficher_BtnRedefineCoords(instance_locale) STRUCT class_VFA &instance_locale Button $instance_locale.Button_RedefineCoords.ctrlName,pos={650,200},size={24,18},proc=ButtonProc_RedefineCoords,title="°",font="Wingdings",fSize=16,fColor=(0xFFFF,0xFFFF,0xFFFF) End
It didn't work since i don't know how to access the members of the structure containing the button instance.
Then I decided to suppress the buttons, and to create a listbox or a popup menu (actually I don't know which solution (1 button per instance, 1 listbox, 1 popup menu...) is the cleanest from a software-engineering point of view)
The main issue is still there : how to refer to a structure from a control (button in the 1st case, item number for the listbox)
I hope I've been clear, I would understand if the description of my problem was confusing. If so, please do not hesitate to ask me.
Thanks in advance!
Best Regards.
Nasser
The only way you can get a filled in structure for a control in Igor is if you set the control's action procedure to a structure based action procedure for that control type. Otherwise, you can use one of the predefined control structures in your code (eg. WMButtonAction), but your code has to fill out all of the values in the structure that are necessary to get your code to work. You could use ControlInfo to get some of the information about the control and put those values into the structure.
January 17, 2011 at 08:25 am - Permalink
To get back a copy of the structure, use GetStruct (again with /S if you are using a string).
The reason a string is most convenient is that it can be stored inside a control using the the control's userdata keyword. In the action procedure, you would use something like
(code not tested, I may have made some stupid mistake...)
Note that there are restrictions on what kind of members you can have in a structure that you store via StructPut. Your structure contains a String member, which is not allowed. You can use a char array, and it will have almost the same functionality. The Variable members are OK.
The STRUCT WMButtonAction member will not be useful, however, as you have found.
The Scatter Plot Matrix package uses StructPut/StructGet to store information into the generated graph window. See File->Example Experiments->Graphing Techniques->Scatter Plot Matrix Demo.
Another example of the use of StructPut/StructGet is the WaveSelectorWidget module. See File->Example Experiments->Programming->WaveSelectorWidgetExample.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
January 17, 2011 at 10:12 am - Permalink
First, I have created a structure, which consists of a string (the name of the chemical), and coordinates (in order to locate the peak corresponding to that chemical, on a spectrum image). The reason why I have defined a structure is that there will be less arguments to be passed in functions, for instance, to quantify the peak. This is working.
Then, my aim is to access the fields of a structure from a control (most likely an item in a listbox).
Here is how I'd like to do it :
> I'd like to re-define the coordinqtes of a peak.
> I choose it from a listbox (I select its name, corresponding to the field "str_Analyte" in the user-defined structure)
> I use the GetMarquee function in order to get the 4 new coordinates values (top left, top right, bottom left, bottom right)
> I affect these values to the Vcmin, VcMax, RTmin, RTmax fields, in the structure instance corresponding to the peak I've choosen in the ListBox.
> I'm happy
Do you know what I mean ?
Best Regards
January 18, 2011 at 05:19 am - Permalink
I don't wish these structure instances to be static. I'd like to be able to redefine the coordinates (for instance).
To be honest, I don't realy know what you mean by "freeze-dried".
Thanks for the info. In the documentation it's written "The structure to be exported must contain only numeric data", fortunately char arrays are supported !
The aim was to create one button per structure instance, so as to directly access the "parent structure" instance fields (e.g. the coordinates of the chemical's peak). Now I'm trying to do the same using an item choosen in a ListBox : How to retrieve the structure instance corresponding to the selected item, in order to access its fields ?
I'll have a look to these examples, to check if their purpose answer my question.
Thank you
Best Regards
January 18, 2011 at 04:01 am - Permalink
I don't mean static in the sense that they can't change, but static in the programmer's sense that they are not local variables that disappear when the function finishes.
Sorry- that's very colloquial American English :) It refers to the process by which food can be dried and made very lightweight for use by hikers or astronauts. In this case, it is intended to mean that the structures are stored away in a special encoding that allows you to re-make the structure later. Just like the hiker or astronaut can re-introduce water to freeze-dried food during cooking to make an edible meal.
And you're trying to coerce Igor's language to look more object-oriented, which you will most likely achieve with only limited success. In the case of a structure for each button, you clearly can use StructPut to store one structure in the control. But with a structure for each row of a ListBox, you have only one control and a number of structures. You might be able to store a structure with an array of structures, but I think that will get cumbersome. Another possibility would be to use multiple named userdata strings to store multiple structures. The structure for row 1 might be stored using userdata(MyStruct1)=... and recovered via GetUserData(panelname, listboxname, "MyStruct"+num2str(rownum)).
Another technique I have used for storing per-row data in a listbox is to use a three-dimensional matrix for the listbox selwave. I then use the extra layers of the selwave (or the listwave- both work) to store private data relating to the rows and columns in the list.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
January 18, 2011 at 09:02 am - Permalink
Thank you for your prompt answer and all those explanations.
You're right, I'm focusing on an Object-oriented programming :)
--> http://www.igorexchange.com/node/1965
I thought the code would be easier to maintain using an Object-Oriented approach.
Regarding your suggestions, I'm going to use the userData variables, that I don't know yet. The most important is that we can access a structure's members from a list's item.
Thank you very much.
Kind regards
January 20, 2011 at 04:50 am - Permalink
Best Regards
January 20, 2011 at 04:42 am - Permalink