Skip to content

Commit

Permalink
PGC_SetAndActivateControl: Make setting a disabled control an error
Browse files Browse the repository at this point in the history
We just to just ignore callers which tried to set a disabled control.
This has led to bugs were calls to PGC_SetAndActivateControl were
ignored.

We therefore now have reworked the disabled control handling by morphing
the ignoreDisabledState optional parameter to mode.

The default value for mode is PGC_MODE_ASSERT_ON_DISABLED which asserts
out on tries to set a disabled control. PGC_MODE_SKIP_ON_DISABLED is the
old behaviour and ignoreDisabledState = 1 can be achieved via
PGC_MODE_FORCE_ON_DISABLED.
  • Loading branch information
t-b committed Nov 6, 2021
1 parent 0e4bc3a commit e29c778
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 27 deletions.
4 changes: 2 additions & 2 deletions Packages/MIES/MIES_AnalysisFunctions_MultiPatchSeq.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,7 @@ Function MSQ_FastRheoEst(panelTitle, s)
for(i = 0; i < NUM_HEADSTAGES; i += 1)
if(statusHS[i] && !statusHSIC[i]) // active non-IC headstage
ctrl = GetPanelControl(i, CHANNEL_TYPE_HEADSTAGE, CHANNEL_CONTROL_CHECK)
PGC_SetAndActivateControl(panelTitle, ctrl, val=CHECKBOX_UNSELECTED, ignoreDisabledState = 1)
PGC_SetAndActivateControl(panelTitle, ctrl, val=CHECKBOX_UNSELECTED, mode = PGC_MODE_FORCE_ON_DISABLED)
endif
endfor

Expand Down Expand Up @@ -1233,7 +1233,7 @@ Function MSQ_FastRheoEst(panelTitle, s)
for(i = 0; i < NUM_HEADSTAGES; i += 1)
if(previousActiveHS[i] && !statusHS[i])
ctrl = GetPanelControl(i, CHANNEL_TYPE_HEADSTAGE, CHANNEL_CONTROL_CHECK)
PGC_SetAndActivateControl(panelTitle, ctrl, val=CHECKBOX_SELECTED, ignoreDisabledState = 1)
PGC_SetAndActivateControl(panelTitle, ctrl, val=CHECKBOX_SELECTED, mode = PGC_MODE_FORCE_ON_DISABLED)
endif
endfor
endif
Expand Down
8 changes: 8 additions & 0 deletions Packages/MIES/MIES_Constants.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -1599,3 +1599,11 @@ StrConstant LABNOTEBOOK_TTL_STIMSETS = "stim sets"
StrConstant LABNOTEBOOK_TTL_SETSWEEPCOUNTS = "set sweep counts"
StrConstant LABNOTEBOOK_TTL_SETCYCLECOUNTS = "set cycle counts"
/// @}

/// @brief Mode flags for PGC_SetAndActivateControl
/// @anchor PGC_MODES
/// @{
Constant PGC_MODE_ASSERT_ON_DISABLED = 0
Constant PGC_MODE_FORCE_ON_DISABLED = 1
Constant PGC_MODE_SKIP_ON_DISABLED = 2
/// @}
52 changes: 35 additions & 17 deletions Packages/MIES/MIES_ProgrammaticGUIControl.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,19 @@ Function PGC_SetAndActivateControlVar(win, control, var)
End

/// @brief Set the control's value and execute the control procedure
/// of the given control (if it exists)
/// of the given control (if it exists).
///
/// @param win Window
/// @param control GUI control
/// @param val [optionality depends on control type] Numeric value to set
/// @param str [optionality depends on control type] String value to set
/// @param switchTab [optional, defaults to false] Switches tabs so that the control is shown
/// @param ignoreDisabledState [optional, defaults to false] Allows to set disabled controls (DANGEROUS!)
/// The function tries to mimick interactive operation as closely as possible.
/// Therefore interacting with disabled controls results in an assertion. See `ignoreDisabledState`
/// for a way to avoid that.
///
/// @param win Window
/// @param control GUI control
/// @param val [optionality depends on control type] Numeric value to set
/// @param str [optionality depends on control type] String value to set
/// @param switchTab [optional, defaults to false] Switches tabs so that the control is shown
/// @param mode [optional, defaults to #PGC_MODE_ASSERT_ON_DISABLED] One of @ref PGC_MODES.
/// Allows to fine tune the behaviour for disabled controls.
///
/// PopupMenus:
/// - Only one of `val` or `str` can be supplied
Expand All @@ -153,21 +158,21 @@ End
///
/// @hidecallgraph
/// @hidecallergraph
Function PGC_SetAndActivateControl(string win, string control, [variable val, string str, variable switchTab, variable ignoreDisabledState])
Function PGC_SetAndActivateControl(string win, string control, [variable val, string str, variable switchTab, variable mode])
string procedure, popupMenuList, popupMenuValue
variable paramType, controlType, variableType, inputWasModified, limitedVal
variable isCheckbox, mode, popupMenuType, index
variable isCheckbox, checkBoxMode, popupMenuType, index

if(ParamIsDefault(switchTab))
switchTab = 0
else
switchTab = !!switchTab
endif

if(ParamIsDefault(ignoreDisabledState))
ignoreDisabledState = 0
if(ParamIsDefault(mode))
mode = PGC_MODE_ASSERT_ON_DISABLED
else
ignoreDisabledState = !!ignoreDisabledState
ASSERT(mode == PGC_MODE_ASSERT_ON_DISABLED || mode == PGC_MODE_FORCE_ON_DISABLED || mode == PGC_MODE_SKIP_ON_DISABLED, "Invalid mode")
endif

// call only once
Expand All @@ -178,9 +183,22 @@ Function PGC_SetAndActivateControl(string win, string control, [variable val, st
endif
controlType = abs(V_flag)

if((V_disable & DISABLE_CONTROL_BIT) && !ignoreDisabledState)
DEBUGPRINT("The control " + control + " in the panel " + win + " is disabled and will not be touched.")
return NaN
if(V_disable & DISABLE_CONTROL_BIT)
switch(mode)
case PGC_MODE_SKIP_ON_DISABLED:
// compatibility behaviour for old code
return NaN
break
case PGC_MODE_ASSERT_ON_DISABLED:
ASSERT(0, "The control " + control + " in the panel " + win + " is disabled and can not be touched.")
break
case PGC_MODE_FORCE_ON_DISABLED:
// just continue
break
default:
ASSERT(0, "Invalid mode")
break
endswitch
endif

procedure = PGC_GetProcAndCheckParamType(S_recreation)
Expand Down Expand Up @@ -251,8 +269,8 @@ Function PGC_SetAndActivateControl(string win, string control, [variable val, st

val = !!val

mode = str2numSafe(GetValueFromRecMacro(REC_MACRO_MODE, S_recreation))
isCheckBox = IsNan(mode) || mode == 1
checkBoxMode = str2numSafe(GetValueFromRecMacro(REC_MACRO_MODE, S_recreation))
isCheckBox = IsNan(checkBoxMode) || checkBoxMode == 1

// emulate the real user experience and do nothing
if(isCheckBox && val == V_Value)
Expand Down
52 changes: 44 additions & 8 deletions Packages/Testing-MIES/UTF_PGCSetAndActivateControl.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -448,13 +448,19 @@ Function PGCT_CheckProc(cba) : CheckBoxControl
return 0
End

static Function PGCT_CheckboxDisabled()
static Function PGCT_ModeFlagDefault()

variable refState, state

SVAR/SDFR=root: panel

PGC_SetAndActivateControl(panel, "checkbox_ctrl_disabled", val = 1)
// defaults to assert
try
PGC_SetAndActivateControl(panel, "checkbox_ctrl_disabled", val = 1)
FAIL()
catch
PASS()
endtry

// no changes
DoUpdate
Expand All @@ -466,18 +472,48 @@ static Function PGCT_CheckboxDisabled()

refState = 0
CHECK_EQUAL_VAR(refState, state)
End

// now it is set
PGC_SetAndActivateControl(panel, "checkbox_ctrl_disabled", val = 1, ignoreDisabledState = 1)
static Function/WAVE VariousModeFlags()

Make/FREE/D modes = {-1, PGC_MODE_ASSERT_ON_DISABLED, PGC_MODE_FORCE_ON_DISABLED, PGC_MODE_SKIP_ON_DISABLED}

return modes
End

// UTF_TD_GENERATOR VariousModeFlags
static Function PGCT_ModeFlag([variable var])
variable refState, state

SVAR/SDFR=root: panel

if(var != PGC_MODE_FORCE_ON_DISABLED && var != PGC_MODE_SKIP_ON_DISABLED)
try
PGC_SetAndActivateControl(panel, "checkbox_ctrl_disabled", val = 1, mode = var)
FAIL()
catch
PASS()
endtry
else
PGC_SetAndActivateControl(panel, "checkbox_ctrl_disabled", val = 1, mode = var)
endif

DoUpdate
ControlInfo/W=$panel checkbox_ctrl_disabled
state = V_Value

NVAR/Z checkedSVAR = checked
CHECK(NVAR_Exists(checkedSVAR))
if(var == PGC_MODE_FORCE_ON_DISABLED)

refState = 1
CHECK_EQUAL_VAR(refState, state)
NVAR/Z checkedSVAR = checked
CHECK(NVAR_Exists(checkedSVAR))

refState = 1
CHECK_EQUAL_VAR(refState, state)
else
NVAR/Z checkedSVAR = checked
CHECK(!NVAR_Exists(checkedSVAR))

refState = 0
CHECK_EQUAL_VAR(refState, state)
endif
End

0 comments on commit e29c778

Please sign in to comment.