check a checkbox from a procedure

I have a complex Igor panel, with many tabs, checkboxes, etc... Is it possible, from the procedure of one object in the panel, to check a checkbox and run the corresponding actions?

Hi Marcel,

Yes.  

//To mark it checked
CheckBox theName value=1

//To remove mark
CheckBox theName value=0

You may need to further specify it if it is not on the target window.

win=winName    Specifies which window or subwindow contains the named control. If not given, then the top-most graph or panel window or subwindow is assumed.

Note this only marks it and does not execute any code attached to it. Now if you have code within the checkbox control and you are using structure based control methods, it is a bit tricky to fire the code with out the user interacting.  One way around it is to separate the functions from the interface code.

Function CheckProc(cba) : CheckBoxControl
    STRUCT WMCheckboxAction &cba

    switch( cba.eventCode )
        case 2: // mouse up
            Variable checked = cba.checked
            if (checked)
                do_Something()
            endif
            break
        case -1: // control being killed
            break
    endswitch

    return 0
End

Function Do_Something()

    Print "Hello World"
End

Andy

Thanks, this is exactly what I needed. Luckily enough, the code for this CheckBox is separated from the interface code.

Great!

 

I will enforce a bit more strongly the statement that Andy makes in passing. The robust way to do these things is using the window designation.

CheckBox theName, win=$panelname, value=1

Also, if you are routinely having an action on one control cause a change in the state of another control, you may also want to use an administrative function that does an update on the state of the panel. This can especially come into play when you want to show/hide various controls depending on for example a pop menu or checkbox selection.

Function update_panelstate()

    ControlInfo/W=$panelname chboxA
    if (v_value)
      Setvariable setvarA, win=$panelname, disable=1
      ...
    else
      Setvariable setvarA, win=$panelname, disable=0
      ...
    endif

   return 0

end

 

Thank you. This is something I am using a lot, although till now, everything is in a single (big) panel!

Marcel

Note,

If the checkbox is linked to global variable:

CheckBox theName, win=$panelname, variable=root:myGlobalvariable

you should simply change value in that variable (myGlobalVariable = 1) and Checkbox will change without any other action. And if you have (as suggested above) do_Something() function, then call that one and you are done. No need to bother changing the checkbox in the panel itself.

 

In reply to by ilavsky

Hi,

What would be even better would be to tie it to wave point.  When designing systems that will evolve over time I often put all the numeric settings into a wave with a dim labels.  That way I have one declaration to do in a function and I can easily see the state of the system by looking at that wave in table.  Typically I have one wave for numeric states and a second for text. This keeps things very clean with needing global variables.  Alas in this case I can't tie the state a wave point.  Just part of the wish list.

Andy

Andy ... Can you give a minimum working example (MWE in the LaTeX stack exchange)? I am confused by what aspect of the control is being tied to a wave point. Specifically, are you tying each point in the wave to a different control on the panel?

My mistake. What I mean is, can you give an example of how tying the state of a control to a wave point WOULD work. I don't see what you have as a vision for this.

Hi Jeff,

I was thinking the same way you can in set variable control. See the set value line to pick a wave and its specific point.

This is an example from an experiment that controlled a phase lock loop amplifier, a Keithley meter, and some LED.  I had all the system state information in one wave and used the row label dimensions to specify. That way with a single wave declaration I had full access and as I added more variables to control I didn't need to worry about messing up previous ones or declaring them in functions.  Also with a simple table command I could see everything. Also I didn't need to a control info command to get a value.  Imagine if you will that all controls could be easily tied to a couple of waves. PopUp menu could have string (S_Value) in a text wave and popup number (V_Value) in a variable wave. Check box could go to a variable wave. Radio buttons could be easily grouped,...  The mind reels!

Andy

I never realized this for set variables. Admittedly I am also not using dimension labels routinely as you are.

My one thought is that what you have done is replace global variables and strings by global waves. As an alternate approach with control panels, I have since been inclined to create a STRUCTURE and a STRUCTURE LOOKUP FUNCTION. Here is an example from my Image Tools package to read the desired load state.

// structure to collect load instructions
Structure S_LoadSettings
    variable what
    variable source
    variable allow16bit
    variable red
    ...
EndStructure

// populate the structure
Function Sf_GetLoadSettings(ls)
    STRUCT S_LoadSettings &ls

    // load what?
    ControlInfo/W=$k_fullpanel popupload_tab0
    ls.what = v_value
   
    // what type of image?
    ControlInfo/W=$k_fullpanel checkgraw_tab0
    ls.graw = v_value
   
    // extract what?
    ControlInfo/W=$k_fullpanel checkgred_tab0
    ls.red = v_value
    ...
   
    return 0
end

The advantage for me is that, as the package expands and other controls are added, I simply need to add a structure variable or string and define the lookup line in the main reading function. I can debug by setting a break-point at the BUTTON action and tracking whether the structure is properly populated.

I would not by this example in any way mean to open a Pandora's box as to which approach is "better", yours or mine. Having done a bit with dimension labels somewhere once or twice, I can see the positive reasons why all controls, not just setvariables, should be able to be defined by using them.

Thanks for the example!

And if you use a substructure for each control, you end up with something that works a bit like a window object. Then you look up a control value with something like mypanel.setvar0.value or mypanel.popup1.sval.

This is excerpted from some code that replaces an earlier version that used the wave-with-dimension-labels approach:

function fillPanelStructure(STRUCT PanelStatusStructure &s)
    getControlValue("thePanel", "popImage", s.image)
    getControlValue("thePanel", "popTraceRGB", s.trace)
    getControlValue("thePanel", "popBGRGB", s.bg)
    getControlValue("thePanel", "setvarRange", s.range)
    getControlValue("thePanel", "checkGaps", s.gaps)
    getControlValue("thePanel", "checkXY", s.XY)
    getControlValue("thePanel", "setvarJump", s.jump)
    getControlValue("thePanel", "setvarTraceName", s.tracename)
    getControlValue("thePanel", "sliderFuzzy", s.fuzzy)
end

Structure PanelStatusStructure
    STRUCT ControlValueStructure image, logX, logY, trace, bg, fuzzy, gaps, XY, jump, range, tracename
EndStructure

Structure ControlValueStructure
    int16 type
    variable value
    string sval
    STRUCT RGBAColor rgb
    variable selcol
EndStructure

function getControlValue(string win, string controlName, STRUCT ControlValueStructure &s)
    ControlInfo /W=$win $controlName
    switch (abs(V_Flag))
        case 3: // popup menu
            s.rgb.red = V_Red
            s.rgb.green = V_Green
            s.rgb.blue = V_Blue
            s.rgb.alpha = V_Alpha
        case 2: // checkbox
        case 4: // valdisplay
        case 5: // SetVariable
        case 7: // slider
        case 8: // tab
            s.type = v_flag
            s.value = v_value
            s.sval = s_value
            break
        case 11: // listbox
            s.type = v_flag
            s.value = v_value
            s.sval = s_value
            s.selcol = v_selcol
            break
        default:
            s.type = v_flag
    endswitch
end

I have been moving toward this sort of thing for user interface code that doesn't need to run especially quickly. I would imagine that populating the structure with multiple calls to controlinfo is much slower than looking up a wave once, so for something like storing parameters for background data acquisition this would be a bad idea.

Hi,

I have been exploiting the use of data labels quite a bit because it in essence allows me to mix data types within waves. An example of some of the techniques (hacks) I play with data labels is in this post .  I use it organize experimental runs by using the row labels as sample id. I would love to see further exploitation of data labels both rows and columns.

Andy

In reply to by hegedus

hegedus wrote:

Hi,

What would be even better would be to tie it to wave point.  When designing systems that will evolve over time I often put all the numeric settings into a wave with a dim labels.  That way I have one declaration to do in a function and I can easily see the state of the system by looking at that wave in table.  Typically I have one wave for numeric states and a second for text. This keeps things very clean with needing global variables.  Alas in this case I can't tie the state a wave point.  Just part of the wish list.

Andy

I agree with you, and I requested this feature long before I started working for WM for the same reason. It is on the official wish list (ticket #3154). Unfortunately it would require substantial changes to code that is already overly tedious.

I will add your "+1" to the feature request.

In practice, I have variables or strings attached to the objects of a panel, then a procedure (called by each object) that writes all the corresponding parameters in a wave, which appears as a table with clear labels (the labels are written in another wave). This table gathers therefore all the information at one glance. It is saved on as a file to pass parameters to a data acquisition program (in Python).