protected override bool UpdateValueCore(string name, string value, UndoRedoRecorder recorder) { if (name != "Code") { return(base.UpdateValueCore(name, value, recorder)); } //Remove the UpdateValue's recording recorder.PopFromUndoGroup(); value = CodeBlockUtils.FormatUserText(value); //Since an empty Code Block Node should not exist, this checks for such instances. // If an empty Code Block Node is found, it is deleted. Since the creation and deletion of // an empty Code Block Node should not be recorded, this method also checks and removes // any unwanted recordings if (value == "") { Code = ""; } else { if (!value.Equals(Code)) { SetCodeContent(value, recorder); } } return(true); }
private void DiscardChangesAndOptionallyRemoveNode(UndoRedoRecorder recorder) { if (!string.IsNullOrEmpty(InnerTextEditor.Text)) { throw new InvalidOperationException( "This method is meant only for empty text box"); } if (createdForNewCodeBlock) { // If this editing was started due to a new code block node, // then by this point the creation of the node would have been // recorded, we need to pop that off the undo stack. Note that // due to various external factors a code block node loaded // from file may be created empty. In such cases, the creation // step would not have been recorded (there was no explicit // creation of the node, it was created from loading of a file), // and nothing should be popped off of the undo stack. // if (recorder.CanUndo) { recorder.PopFromUndoGroup(); // Pop off creation action. } } else { // If the editing was started for an existing code block node, // and user deletes the text contents, it should be restored to // the original codes. InnerTextEditor.Text = codeBlockNode.Code; } }
public bool HandleModelEventCore(string eventName, UndoRedoRecorder recorder) { if (eventName == "AddInPort") { AddInputToModel(); model.RegisterAllPorts(); return(true); // Handled here. } if (eventName == "RemoveInPort") { // When an in-port is removed, it is possible that a connector // is almost removed along with it. Both node modification and // connector deletion have to be recorded as one action group. // But before HandleModelEventCore is called, node modification // has already been recorded (in WorkspaceModel.SendModelEvent). // For that reason, that entry on the undo-stack needs to be // popped (the node modification will be recorded here instead). // recorder.PopFromUndoGroup(); RecordModels(recorder); RemoveInputFromModel(); model.RegisterAllPorts(); return(true); // Handled here. } return(false); // base.HandleModelEventCore(eventName); }
public void TestPopFromUndoGroup() { //Assert that it cannot pop from an empty undostack Assert.Throws <InvalidOperationException>(() => { recorder.PopFromUndoGroup(); }); //Add models workspace.AddModel(new DummyModel(1, 10)); workspace.AddModel(new DummyModel(2, 10)); Assert.AreEqual(true, recorder.CanUndo); Assert.AreEqual(false, recorder.CanRedo); recorder.Undo(); //Assert that there was an Action Group that was just pushed on top of the undo stack Assert.Throws <InvalidOperationException>(() => { recorder.PopFromUndoGroup(); }); }
private void CommitChanges(UndoRedoRecorder recorder) { // Code block editor can lose focus in many scenarios (e.g. switching // of tabs or application), if there has not been any changes, do not // commit the change. // if (!nodeModel.Code.Equals(InnerTextEditor.Text)) { nodeViewModel.DynamoViewModel.ExecuteCommand( new DynCmd.UpdateModelValueCommand( nodeViewModel.WorkspaceViewModel.Model.Guid, nodeModel.GUID, "Code", InnerTextEditor.Text)); } if (createdForNewCodeBlock) { // If this editing was started due to a new code block node, // then by this point there would have been two action groups // recorded on the undo-stack: one for node creation, and // another for node editing (as part of ExecuteCommand above). // Pop off the two action groups... // recorder.PopFromUndoGroup(); // Pop off modification action. // Note that due to various external factors a code block node // loaded from file may be created empty. In such cases, the // creation step would not have been recorded (there was no // explicit creation of the node, it was created from loading // of a file), and nothing should be popped off of the undo stack. if (recorder.CanUndo) { recorder.PopFromUndoGroup(); // Pop off creation action. } // ... and record this new node as new creation. using (recorder.BeginActionGroup()) { recorder.RecordCreationForUndo(nodeModel); } } }
internal static void RecordModelsForUndo(Dictionary <ModelBase, UndoRedoRecorder.UserAction> models, UndoRedoRecorder recorder) { if (null == recorder) { return; } if (!ShouldProceedWithRecording(models)) { return; } if (null != savedModels) { // Before an existing connector is reconnected, we have one action group // which records the deletion of the connector. Pop that out so that we can // record the deletion and reconnection in one action group. recorder.PopFromUndoGroup(); } using (recorder.BeginActionGroup()) { if (null != savedModels) { foreach (var modelPair in savedModels) { recorder.RecordDeletionForUndo(modelPair); } savedModels = null; } foreach (var modelPair in models) { switch (modelPair.Value) { case UndoRedoRecorder.UserAction.Creation: recorder.RecordCreationForUndo(modelPair.Key); break; case UndoRedoRecorder.UserAction.Deletion: recorder.RecordDeletionForUndo(modelPair.Key); break; case UndoRedoRecorder.UserAction.Modification: recorder.RecordModificationForUndo(modelPair.Key); break; } } } }