Skip to content

Commit a23224f

Browse files
[Cherry-pick] [DYN-8528] Can't undo changes to curve mapper (#16229)
Co-authored-by: Ivo Petrov <[email protected]>
1 parent 9c8f571 commit a23224f

File tree

3 files changed

+109
-41
lines changed

3 files changed

+109
-41
lines changed

src/Libraries/CoreNodeModels/CurveMapperNodeModel.cs

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,10 @@ public class CurveMapperNodeModel : NodeModel
7878
private double dynamicCanvasSize = defaultCanvasSize;
7979
private bool isLocked;
8080
private bool isResizing;
81+
private bool isRestoringUndo;
8182

8283
#region Curves & Point Data
83-
84+
8485
/// <summary> Point data for the 1st control point of the linear curve. </summary>
8586
[JsonProperty]
8687
public ControlPointData LinearCurveControlPointData1 { get; private set; }
@@ -334,6 +335,7 @@ public GraphTypes SelectedGraphType
334335
selectedGraphType = value;
335336
GenerateRenderValues();
336337
RaisePropertyChanged(nameof(SelectedGraphType));
338+
RaisePropertyChanged(nameof(SelectedGraphTypeDescription));
337339
}
338340
}
339341

@@ -367,10 +369,25 @@ public bool IsResizing
367369
}
368370
}
369371

372+
/// <summary> Indicates whether the node is currently restoring its state during undo. </summary>
373+
[JsonIgnore]
374+
public bool IsRestoringUndo
375+
{
376+
get => isRestoringUndo;
377+
private set
378+
{
379+
if (isRestoringUndo != value)
380+
{
381+
isRestoringUndo = value;
382+
}
383+
}
384+
}
385+
370386
/// <summary> Indicates that this node supports resizing via UI. </summary>
371387
[JsonIgnore]
372388
public override bool IsResizable => true;
373389

390+
374391
#region Constructors
375392

376393
public CurveMapperNodeModel()
@@ -980,22 +997,47 @@ protected override void SerializeCore(XmlElement element, SaveContext context)
980997
SavePointData(element, "Gaussian4", GaussianCurveControlPointData4);
981998
break;
982999
}
983-
}
1000+
}
9841001

9851002
protected override void DeserializeCore(XmlElement element, SaveContext context)
9861003
{
9871004
base.DeserializeCore(element, context);
9881005

1006+
// Suppress undo-related reactions
1007+
IsRestoringUndo = true;
1008+
9891009
// Restore the selected graph type
9901010
var typeAttr = element.GetAttribute(nameof(SelectedGraphType));
9911011
if (!string.IsNullOrEmpty(typeAttr) && Enum.TryParse(typeAttr, out GraphTypes parsedType))
992-
SelectedGraphType = parsedType;
1012+
{
1013+
if (SelectedGraphType != parsedType)
1014+
{
1015+
SelectedGraphType = parsedType;
1016+
RaisePropertyChanged(nameof(SelectedGraphType));
1017+
}
1018+
}
9931019

1020+
// Restore locked state
9941021
if (bool.TryParse(element.GetAttribute(nameof(IsLocked)), out var locked))
995-
IsLocked = locked;
1022+
{
1023+
if (IsLocked != locked)
1024+
{
1025+
IsLocked = locked;
1026+
RaisePropertyChanged(nameof(IsLocked));
1027+
}
1028+
}
9961029

1030+
// Restore canvas size
9971031
if (double.TryParse(element.GetAttribute(nameof(DynamicCanvasSize)), out var canvasSize))
998-
DynamicCanvasSize = canvasSize;
1032+
{
1033+
if (DynamicCanvasSize != canvasSize)
1034+
{
1035+
DynamicCanvasSize = canvasSize;
1036+
RaisePropertyChanged(nameof(DynamicCanvasSize));
1037+
}
1038+
}
1039+
1040+
IsRestoringUndo = false;
9991041

10001042
switch (SelectedGraphType)
10011043
{

src/Libraries/CoreNodeModelsWpf/CurveMapper/CurveMapperControl.xaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@
3939
<Grid>
4040
<Grid x:Name="MainGrid"
4141
MinWidth="325"
42-
MinHeight="340"
43-
Width="{Binding MainGridWidth, Mode=TwoWay}"
44-
Height="{Binding MainGridHeight, Mode=TwoWay}">
42+
MinHeight="340">
4543
<Grid.RowDefinitions>
4644
<RowDefinition Height="*" />
4745
<RowDefinition Height="35" />
@@ -156,7 +154,8 @@
156154
Margin="10,0,0,0"
157155
VerticalAlignment="Center"
158156
ItemsSource="{Binding GraphTypesList}"
159-
SelectedItem="{Binding SelectedGraphTypeDescription, Mode=TwoWay}">
157+
SelectedItem="{Binding SelectedGraphTypeDescription, Mode=TwoWay}"
158+
DropDownOpened="GraphTypeComboBox_DropDownOpened">
160159
<ComboBox.Style>
161160
<Style BasedOn="{StaticResource RefreshComboBox}" TargetType="ComboBox">
162161
<Style.Triggers>

src/Libraries/CoreNodeModelsWpf/CurveMapper/CurveMapperControl.xaml.cs

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -105,29 +105,28 @@ public CurveMapperControl(CurveMapperNodeModel model, double canvasSize, NodeVie
105105
Width = canvasSize + controlLabelsWidth;
106106
Height = canvasSize + controlLabelsHeight;
107107

108-
109108
model.PropertyChanged += NodeModel_PropertyChanged;
110-
this.Unloaded += Unload;
109+
resizeThumb.DragStarted += ResizeThumb_DragStarted;
110+
Unloaded += Unload;
111111

112112
DrawGrid();
113113

114114
// Dictionary to map UI control points to their corresponding data
115-
var controlPointsMap = BuildControlPointsDictionary();
116-
RecreateControlPoints(controlPointsMap);
117-
118-
RenderCurve();
119-
115+
UpdateUIFromModel();
120116
ToggleControlPointsLock();
121117
UpdateLockButton();
122118
}
123119

124-
private void OnControlPointDragCompleted()
120+
private void RecordUndo()
125121
{
126-
var workspace = nodeViewModel?.WorkspaceViewModel?.Model;
127-
if (workspace != null)
128-
{
129-
WorkspaceModel.RecordModelForModification(curveMapperNodeModel, workspace.UndoRecorder);
130-
}
122+
var undoRecorder = nodeViewModel.WorkspaceViewModel.Model.UndoRecorder;
123+
WorkspaceModel.RecordModelForModification(curveMapperNodeModel, undoRecorder);
124+
}
125+
126+
private void OnControlPointDragStarted()
127+
{
128+
if (!curveMapperNodeModel.IsLocked)
129+
RecordUndo();
131130
}
132131

133132
private void RenderCurve()
@@ -201,23 +200,30 @@ private void ResetButton_Click(object sender, RoutedEventArgs e)
201200
{
202201
if (curveMapperNodeModel.IsLocked) return;
203202

203+
RecordUndo();
204+
204205
curveMapperNodeModel.ResetControlPointData();
205206

206-
// Dictionary to map UI control points to their corresponding data
207-
var controlPointsResetMap = BuildControlPointsDictionary();
208-
RecreateControlPoints(controlPointsResetMap);
209-
RenderCurve();
207+
UpdateUIFromModel();
210208
}
211209

212210
private void LockButton_Click(object sender, RoutedEventArgs e)
213211
{
214-
var button = sender as Button;
215-
if (button != null)
216-
{
217-
curveMapperNodeModel.IsLocked = !curveMapperNodeModel.IsLocked;
218-
UpdateLockButton();
219-
ToggleControlPointsLock();
220-
}
212+
RecordUndo();
213+
214+
curveMapperNodeModel.IsLocked = !curveMapperNodeModel.IsLocked;
215+
UpdateLockButton();
216+
ToggleControlPointsLock();
217+
}
218+
219+
private void GraphTypeComboBox_DropDownOpened(object sender, EventArgs e)
220+
{
221+
RecordUndo();
222+
}
223+
224+
private void ResizeThumb_DragStarted(object sender, DragStartedEventArgs e)
225+
{
226+
RecordUndo();
221227
}
222228

223229
private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -245,14 +251,24 @@ private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e
245251
}
246252

247253
RenderCurve();
254+
255+
if (curveMapperNodeModel.IsRestoringUndo)
256+
{
257+
double canvasSize = curveMapperNodeModel.DynamicCanvasSize;
258+
Width = canvasSize + controlLabelsWidth;
259+
Height = canvasSize + controlLabelsHeight;
260+
DrawGrid();
261+
}
248262
}
249263

250264
if (e.PropertyName == nameof(curveMapperNodeModel.SelectedGraphType))
251265
{
252-
var controlPointsMap = BuildControlPointsDictionary();
253-
RecreateControlPoints(controlPointsMap);
254-
RenderCurve();
255-
ToggleControlPointsLock();
266+
UpdateUIFromModel();
267+
268+
if (!curveMapperNodeModel.IsRestoringUndo)
269+
{
270+
ToggleControlPointsLock();
271+
}
256272
}
257273

258274
if (e.PropertyName == nameof(curveMapperNodeModel.RenderValuesX) ||
@@ -272,9 +288,13 @@ private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e
272288

273289
if (e.PropertyName == "ControlPointsDeserialized")
274290
{
275-
var controlPointsMap = BuildControlPointsDictionary();
276-
RecreateControlPoints(controlPointsMap);
277-
RenderCurve();
291+
UpdateUIFromModel();
292+
}
293+
294+
if (e.PropertyName == nameof(curveMapperNodeModel.IsLocked))
295+
{
296+
UpdateLockButton();
297+
ToggleControlPointsLock();
278298
}
279299
}
280300

@@ -320,7 +340,7 @@ private void RecreateControlPoints(Dictionary<GraphTypes, (List<string> pointNam
320340
isOrthogonal,
321341
isVertical);
322342

323-
newPoint.DragCompleted += (s, e) => OnControlPointDragCompleted();
343+
newPoint.DragStarted += (s, e) => OnControlPointDragStarted();
324344

325345
pointField?.SetValue(this, newPoint);
326346
GraphCanvas.Children.Add(newPoint);
@@ -339,6 +359,13 @@ private void RecreateControlPoints(Dictionary<GraphTypes, (List<string> pointNam
339359
}
340360
}
341361

362+
private void UpdateUIFromModel()
363+
{
364+
var controlPointsMap = BuildControlPointsDictionary();
365+
RecreateControlPoints(controlPointsMap);
366+
RenderCurve();
367+
}
368+
342369
private void UpdateControlPointPosition(UIElement controlPoint, ControlPointData dataPoint, double newSize)
343370
{
344371
if (controlPoint != null && dataPoint != null)

0 commit comments

Comments
 (0)