From ffc8a76ad8dfd4afc8c3d7283016394734d58f8d Mon Sep 17 00:00:00 2001 From: Benjamin Popp Date: Mon, 27 May 2019 20:19:10 -0500 Subject: [PATCH] Update table pointer field when data gets moved --- .../Tools/IArrayElementViewModel.cs | 13 +++++++++-- .../ViewModels/Tools/TableTool.cs | 5 +++-- src/HexManiac.Tests/NestedTablesTests.cs | 22 +++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/HexManiac.Core/ViewModels/Tools/IArrayElementViewModel.cs b/src/HexManiac.Core/ViewModels/Tools/IArrayElementViewModel.cs index 8a74390b..f63a9233 100644 --- a/src/HexManiac.Core/ViewModels/Tools/IArrayElementViewModel.cs +++ b/src/HexManiac.Core/ViewModels/Tools/IArrayElementViewModel.cs @@ -66,6 +66,10 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { (History, Model, Name, Start, Length) = (history, model, name, start, length); content = strategy.UpdateViewModelFromModel(this); } + + public void RefreshControlFromModelChange() { + TryUpdate(ref content, strategy.UpdateViewModelFromModel(this), nameof(Content)); + } } public class TextFieldStratgy : IFieldArrayElementViewModelStrategy { @@ -218,6 +222,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { public class TextStreamArrayElementViewModel : ViewModelCore, IArrayElementViewModel { private readonly ChangeHistory history; + private readonly FieldArrayElementViewModel matchingField; private readonly IDataModel model; private readonly string name; private readonly int start; @@ -236,7 +241,10 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { var run = model.GetNextRun(destination); var data = PCSString.Convert(content); var newRun = model.RelocateForExpansion(history.CurrentChange, run, data.Count); - if (run.Start != newRun.Start) DataMoved?.Invoke(this, (run.Start, newRun.Start)); + if (run.Start != newRun.Start) { + DataMoved?.Invoke(this, (run.Start, newRun.Start)); + matchingField.RefreshControlFromModelChange(); + } run = newRun; for (int i = 0; i < data.Count; i++) history.CurrentChange.ChangeData(model, run.Start + i, data[i]); for (int i = data.Count; i < run.Length; i++) history.CurrentChange.ChangeData(model, run.Start + i, 0xFF); @@ -246,8 +254,9 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { } } - public TextStreamArrayElementViewModel(ChangeHistory history, IDataModel model, string name, int start) { + public TextStreamArrayElementViewModel(ChangeHistory history, FieldArrayElementViewModel matchingField, IDataModel model, string name, int start) { this.history = history; + this.matchingField = matchingField; this.model = model; this.name = name; this.start = start; diff --git a/src/HexManiac.Core/ViewModels/Tools/TableTool.cs b/src/HexManiac.Core/ViewModels/Tools/TableTool.cs index eac504c2..8e9918bd 100644 --- a/src/HexManiac.Core/ViewModels/Tools/TableTool.cs +++ b/src/HexManiac.Core/ViewModels/Tools/TableTool.cs @@ -162,9 +162,10 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { Children.Add(viewModel); viewModel.DataChanged += ForwardModelChanged; if (item is ArrayRunPointerSegment pointerSegment) { - if (pointerSegment.DestinationDataMatchesPointerFormat(model, history.CurrentChange, model.ReadPointer(itemAddress))) { + var destination = model.ReadPointer(itemAddress); + if (destination != Pointer.NULL && pointerSegment.DestinationDataMatchesPointerFormat(model, history.CurrentChange, destination)) { if (pointerSegment.InnerFormat == $"{PCSRun.StringDelimeter}{PCSRun.StringDelimeter}") { - var streamElement = new TextStreamArrayElementViewModel(history, model, item.Name, itemAddress); + var streamElement = new TextStreamArrayElementViewModel(history, (FieldArrayElementViewModel)viewModel, model, item.Name, itemAddress); streamElement.DataChanged += ForwardModelChanged; streamElement.DataMoved += ForwardModelDataMoved; Children.Add(streamElement); diff --git a/src/HexManiac.Tests/NestedTablesTests.cs b/src/HexManiac.Tests/NestedTablesTests.cs index f4baa2a5..c4b295a2 100644 --- a/src/HexManiac.Tests/NestedTablesTests.cs +++ b/src/HexManiac.Tests/NestedTablesTests.cs @@ -12,12 +12,14 @@ namespace HavenSoft.HexManiac.Tests { private readonly PokemonModel model; private readonly ModelDelta token = new ModelDelta(); private readonly byte[] data = new byte[0x200]; + private readonly List messages = new List(); private readonly List errors = new List(); public NestedTablesTests() { model = new PokemonModel(data); viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.OnError += (sender, e) => errors.Add(e); + viewPort.OnMessage += (sender, e) => messages.Add(e); } [Fact] @@ -137,5 +139,25 @@ namespace HavenSoft.HexManiac.Tests { Assert.Equal(2, viewPort.Tools.TableTool.Children.Count); Assert.IsType(viewPort.Tools.TableTool.Children[1]); } + + [Fact] + public void UpdateViaToolStreamFieldThatCausesMoveAlsoUpdatesToolPointerField() { + viewPort.Edit("FF 00 23"); // put a valid end, then a spare byte, then some junk. This'll cause a move after adding enough characters. + viewPort.SelectionStart = new Point(0, 0); + viewPort.Edit("^text\"\" ?\""); + + viewPort.SelectionStart = new Point(0, 4); + viewPort.Edit("^table[description<\"\">]4 <000000>"); // note that this auto-scrolls, since a table was created + viewPort.SelectionStart = new Point(0, 0); + var textViewModel = (TextStreamArrayElementViewModel)viewPort.Tools.TableTool.Children[1]; + + // act: use the tool to change the content, forcing a repoint + messages.Clear(); + textViewModel.Content = "Xyz"; + var pointerViewModel = (FieldArrayElementViewModel)viewPort.Tools.TableTool.Children[0]; + + Assert.Single(messages); // we repointed + Assert.NotEqual("<000000>", pointerViewModel.Content); // other tool field was updated + } } }