NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Bad Undo behavior with OnNewStep added end block step

Solved!
Go to solution

Hello,

 

I am working on StepTypes that requires block structure, like loops in TestStand (using TestStand 2012). I use OnNewStep SubStep to insert the end block step when the start block step is instanciated.

 

I do no manage to get a proper Undo behavior with this Steps:

  • If I do not use SequenceFile.IncChangeCount in the OnNewStep SubStep, when I select Undo in Sequence Editor, the only start block step is removed, the end block remains. My understanding, it is the expected behavior : TestStand Engine do not know that the end block step has been added, it has no reason to remove it.
    However, I would prefer removing both start and end block steps, just like TestStand do with While, DoWhil or For loops.

  • If I do a SequenceFile.IncChangeCount in the OnNewStep SubStep, when I select Undo in the Sequence Editor, I get the following error, and nothing is removed nor undone from the sequence:

    UndoErrorFLoopStep.png

I guess TestStand increments the ChangeCount when I insert a Step, and OnNewStep also increment the ChangeCount, while the operation should be considered as a unique action.

 

I found in the documentation the class UndoStack, with the method AggregateTopUndoItems Method that, I guess, may be the solution. But UndoStack seems be be accessible only from ApplicationMgr and SequenceFileViewMgr (which are not accessible from the sequence context).

 

Any idea to get a similar behavior to native flow control step, with proper Undo?

 

Best regards,

0 Kudos
Message 1 of 2
(3,810 Views)
Solution
Accepted by topic author Mathieu_R.

Well, I've found a solution by looking at what is done in CommonFlow.cpp (<ProgramFiles>\National Instruments\TestStand 2012\Components\StepTypes\FlowControl).

 

For information purposes, here is the code:

 

// insert a matching END step after the new step
static void OnNewStepWithEndStepFunction(SequenceContextPtr &sequenceContext)
{
	if (!sequenceContext->Sequence->HasMismatchedBlocks)
		return;

	PropertyObjectFilePtr	file = sequenceContext->SequenceFile->AsPropertyObjectFile();
	StepPtr endStep = sequenceContext->Engine->NewStep("", gEndStepTypeName);		
	UndoItemCreatorPtr undoItemCreator = sequenceContext->Engine->NewUndoItemCreator(EditKind_InsertStep, file, L"");

	undoItemCreator->BeginEdit(endStep->AsPropertyObject());
	sequenceContext->Sequence->InsertStep(endStep, sequenceContext->StepIndex + 1, sequenceContext->StepGroup);
	undoItemCreator->EndEdit();

	_variant_t	found;
	endStep->Name = (char *)sequenceContext->Engine->GetResourceString("FLOW_CONTROL_STEPS", "END_DEF_STEP_NAME", "", &found);

	file->IncChangeCount();

	// do this or the step type won't immediately show up as being used by the file
	file->TypeUsageList->AddUsedTypes(endStep->AsPropertyObject());

	undoItemCreator->CreateAndPostUndoItem(CreateUndoItemOption_NoOptions, TS::ApplicationSite_DefaultSite);
}

So the trick is to instanciate a UndoItemCreator that points to the current SequenceFIle, to call BeginEdit with, as argument, the Step to insert as PropertyObjetct, before calling the InsertStep method, and then call EndEdit method. Increment the file change count, add the Step as PropertyObject to the file TypeUsedList, and finally call CreateAndPostUndoItem method.

 

...Happy!

Message 2 of 2
(3,806 Views)