mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-10-02 05:06:35 -05:00
make string tool interact with main viewport in the expected ways.
This commit is contained in:
@@ -94,7 +94,7 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
bool isEscaped = index > Start && data[index - 1] == PCSString.Escape;
|
||||
var fullString = PCSString.Convert(data, Start, Length);
|
||||
if (isEscaped) {
|
||||
return new EscapedPCS(Start, index-Start, fullString, data[Start + index]);
|
||||
return new EscapedPCS(Start, index-Start, fullString, data[index]);
|
||||
} else {
|
||||
var character = PCSString.Convert(data, index, 1).Substring(1); // trim leading "
|
||||
if (index == Start) character = '"' + character; // include the opening quotation mark, only for the first character
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
result.Add((byte)i);
|
||||
index += PCS[i].Length - 1;
|
||||
if (i == Escape) {
|
||||
result.Add(byte.Parse(input.Substring(index, 2), NumberStyles.HexNumber));
|
||||
result.Add(byte.Parse(input.Substring(index + 1, 2), NumberStyles.HexNumber));
|
||||
index += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
@@ -64,8 +65,18 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
if (run == null) return;
|
||||
var bytes = PCSString.Convert(content);
|
||||
var newRun = model.RelocateForExpansion(run, bytes.Count);
|
||||
if (run.Start != newRun.Start) ModelDataMoved?.Invoke(this, (run.Start, newRun.Start));
|
||||
|
||||
// clear out excess bytes that are no longer in use
|
||||
if (run.Start == newRun.Start) {
|
||||
for (int i = bytes.Count; i < run.Length; i++) model[run.Start + i] = 0xFF;
|
||||
}
|
||||
|
||||
for (int i = 0; i < bytes.Count; i++) model[newRun.Start + i] = bytes[i];
|
||||
model.ObserveRunWritten(new PCSRun(newRun.Start, bytes.Count, newRun.PointerSources));
|
||||
run = new PCSRun(newRun.Start, bytes.Count, newRun.PointerSources);
|
||||
model.ObserveRunWritten(run);
|
||||
ModelDataChanged?.Invoke(this, run);
|
||||
TryUpdate(ref address, newRun.Start, nameof(Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,6 +93,9 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<IFormattedRun> ModelDataChanged;
|
||||
public event EventHandler<(int originalLocation, int newLocation)> ModelDataMoved;
|
||||
|
||||
public PCSTool(IModel model) => this.model = model;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +226,8 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
Model = model ?? new BasicModel(file.Contents);
|
||||
FileName = file.Name;
|
||||
Tools = new ToolTray(Model);
|
||||
Tools.StringTool.ModelDataChanged += ModelChangedByTool;
|
||||
Tools.StringTool.ModelDataMoved += ModelDataMovedByTool;
|
||||
|
||||
scroll = new ScrollRegion { DataLength = Model.Count };
|
||||
scroll.PropertyChanged += ScrollPropertyChanged;
|
||||
@@ -748,7 +750,7 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
// last character edit: might require relocation
|
||||
var newRun = Model.RelocateForExpansion(run, run.Length + extraBytesNeeded);
|
||||
if (newRun != run) {
|
||||
var offset = memoryLocation - scroll.ViewPointToDataIndex(new Point(0, 0));
|
||||
var offset = memoryLocation - scroll.DataIndex;
|
||||
selection.GotoAddress(newRun.Start + pcs.Position - offset);
|
||||
memoryLocation += newRun.Start - run.Start;
|
||||
run = newRun;
|
||||
@@ -805,6 +807,21 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
selection.PropertyChanged += SelectionPropertyChanged;
|
||||
}
|
||||
|
||||
private void ModelChangedByTool(object sender, IFormattedRun run) {
|
||||
if (run.Start < scroll.ViewPointToDataIndex(new Point(Width - 1, Height - 1)) || run.Start + run.Length > scroll.DataIndex) {
|
||||
// there's some visible data that changed
|
||||
RefreshBackingData();
|
||||
}
|
||||
}
|
||||
|
||||
private void ModelDataMovedByTool(object sender, (int originalLocation, int newLocation) locations) {
|
||||
if (scroll.DataIndex <= locations.originalLocation && locations.originalLocation < scroll.ViewPointToDataIndex(new Point(Width - 1, Height - 1))) {
|
||||
// data was moved from onscreen: follow it
|
||||
int offset = locations.originalLocation - scroll.DataIndex;
|
||||
selection.GotoAddress(locations.newLocation - offset);
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshBackingData() {
|
||||
currentView = new HexElement[Width, Height];
|
||||
IFormattedRun run = null;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
@@ -8,12 +10,12 @@ namespace HavenSoft.Gen3Hex.Tests {
|
||||
public class ToolTests {
|
||||
[Fact]
|
||||
public void ViewPortHasTools() {
|
||||
var viewPort = new ViewPort(new Core.Models.LoadedFile("file.txt", new byte[100]));
|
||||
var viewPort = new ViewPort(new LoadedFile("file.txt", new byte[100]));
|
||||
Assert.True(viewPort.HasTools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StringToolCanMoveData() {
|
||||
public void StringToolCanOpenOnChosenData() {
|
||||
var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray();
|
||||
var model = new PointerAndStringModel(buffer);
|
||||
var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 };
|
||||
@@ -26,6 +28,57 @@ namespace HavenSoft.Gen3Hex.Tests {
|
||||
Assert.IsType<PCSTool>(viewPort.Tools[viewPort.Tools.SelectedIndex]);
|
||||
}
|
||||
|
||||
// TODO tool changes should be immediately reflected in the ViewPort
|
||||
[Fact]
|
||||
public void StringToolEditsAreReflectedInViewPort() {
|
||||
var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray();
|
||||
var model = new PointerAndStringModel(buffer);
|
||||
var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 };
|
||||
viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>");
|
||||
viewPort.Tools.StringTool.Address = 0;
|
||||
|
||||
viewPort.Tools.StringTool.Content = "Some Test"; // Text -> Test
|
||||
var pcs = (PCS)viewPort[7, 0].Format;
|
||||
Assert.Equal("s", pcs.ThisCharacter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StringToolCanMoveData() {
|
||||
var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray();
|
||||
var model = new PointerAndStringModel(buffer);
|
||||
var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 };
|
||||
viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>");
|
||||
var toolProperties = new List<string>();
|
||||
viewPort.Tools.StringTool.PropertyChanged += (sender, e) => toolProperties.Add(e.PropertyName);
|
||||
viewPort.Tools.StringTool.Address = 0;
|
||||
|
||||
toolProperties.Clear();
|
||||
viewPort.Tools.StringTool.Content = "Some More Text";
|
||||
Assert.Contains("Address", toolProperties);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ViewPortMovesWhenStringToolMovesData() {
|
||||
var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray();
|
||||
var model = new PointerAndStringModel(buffer);
|
||||
var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 };
|
||||
viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>");
|
||||
viewPort.Tools.StringTool.Address = 0;
|
||||
|
||||
viewPort.Tools.StringTool.Content = "Some More Text";
|
||||
Assert.NotEqual(0, int.Parse(viewPort.Headers[0], NumberStyles.HexNumber));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StringToolMultiCharacterDeleteCleansUpUnusedBytes() {
|
||||
var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray();
|
||||
var model = new PointerAndStringModel(buffer);
|
||||
var viewPort = new ViewPort(new LoadedFile("test.txt", buffer), model) { Width = 0x10, Height = 0x10 };
|
||||
viewPort.Edit("^bob\"\" \"Some Text\" 00 <000100>");
|
||||
viewPort.Tools.StringTool.Address = 0;
|
||||
|
||||
viewPort.Tools.StringTool.Content = "Some "; // removed 'Text' from the end
|
||||
|
||||
Assert.Equal(0xFF, model[7]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<TextBox Text="{Binding StringTool.Address, Converter={StaticResource Hex}}" Margin="5,15"/>
|
||||
<TextBox Text="{Binding StringTool.Content}" Margin="5,15" AcceptsReturn="True" MinHeight="50" TextWrapping="Wrap"/>
|
||||
<TextBox Text="{Binding StringTool.Content, UpdateSourceTrigger=PropertyChanged}" Margin="5,15" AcceptsReturn="True" MinHeight="50" MinWidth="50" MaxWidth="150" TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ScrollBar DockPanel.Dock="Right"
|
||||
|
||||
Reference in New Issue
Block a user