mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-05-22 21:40:31 -05:00
add a "clear format" right-click option
when adding an anchor, search for pointers to that spot
This commit is contained in:
parent
75a65ce502
commit
bc62a3bb7e
|
|
@ -700,7 +700,12 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
|||
/// </returns>
|
||||
private IReadOnlyList<int> GetSourcesPointingToNewAnchor(ModelDelta changeToken, string anchorName) {
|
||||
if (!addressForAnchor.TryGetValue(anchorName, out int location)) return new List<int>(); // new anchor is unnamed, so nothing points to it yet
|
||||
if (!unmappedNameToSources.TryGetValue(anchorName, out var sources)) return new List<int>(); // no pointer was waiting for this anchor to be created
|
||||
|
||||
if (!unmappedNameToSources.TryGetValue(anchorName, out var sources)) {
|
||||
// no pointer was waiting for this anchor to be created
|
||||
// but the user things there's something pointing here
|
||||
return SearchForPointersToAnchor(changeToken, location);
|
||||
}
|
||||
|
||||
foreach (var source in sources) {
|
||||
var index = BinarySearch(source);
|
||||
|
|
@ -715,6 +720,27 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
|||
return sources;
|
||||
}
|
||||
|
||||
private IReadOnlyList<int> SearchForPointersToAnchor(ModelDelta changeToken, int address) {
|
||||
var results = new List<int>();
|
||||
|
||||
for (int i = 3; i < RawData.Length; i++) {
|
||||
if (RawData[i] != 0x08 && RawData[i] != 0x09) continue;
|
||||
int destination = ReadPointer(i - 3);
|
||||
if (destination != address) continue;
|
||||
var index = BinarySearch(i-3);
|
||||
if (index > 0) continue;
|
||||
index = ~index;
|
||||
if (runs[index].Start <= i) continue;
|
||||
if (index > 0 && runs[index - 1].Start + runs[index - 1].Length > i - 3) continue;
|
||||
var newRun = new PointerRun(i - 3);
|
||||
runs.Insert(index, newRun);
|
||||
changeToken.AddRun(newRun);
|
||||
results.Add(i - 3);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private IFormattedRun MoveRun(ModelDelta changeToken, IFormattedRun run, int newStart) {
|
||||
// repoint
|
||||
foreach (var source in run.PointerSources) {
|
||||
|
|
@ -774,6 +800,9 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
|||
return true;
|
||||
}
|
||||
|
||||
// if an existing run starts exactly at start, return that index
|
||||
// otherwise, return a number such that ~index would be inserted into the list at the correct index
|
||||
// so ~index - 1 is the previous run, and ~index is the next run
|
||||
private int BinarySearch(int start) {
|
||||
var index = runs.BinarySearch(new CompareFormattedRun(start), FormattedRunComparer.Instance);
|
||||
return index;
|
||||
|
|
|
|||
|
|
@ -328,6 +328,12 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
|||
|
||||
public bool IsSelected(Point point) => selection.IsSelected(point);
|
||||
|
||||
public void ClearFormat(Point point) {
|
||||
var dataIndex = scroll.ViewPointToDataIndex(point);
|
||||
Model.ClearFormat(history.CurrentChange, dataIndex, 1);
|
||||
RefreshBackingData();
|
||||
}
|
||||
|
||||
public void Edit(string input) {
|
||||
exitEditEarly = false;
|
||||
using (Tools.DeferUpdates) {
|
||||
|
|
|
|||
|
|
@ -695,5 +695,34 @@ namespace HavenSoft.Gen3Hex.Tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddingAnchorShouldSearchForPointersToThatLocation() {
|
||||
var data = new byte[0x200];
|
||||
var model = new PokemonModel(data);
|
||||
var change = new ModelDelta();
|
||||
model.WritePointer(change, 0x23, 0x050); // a pointer that isn't 4-byte aligned, pointing to data that is
|
||||
model.WritePointer(change, 0x10, 0x087); // a pointer that is 4-byte aligned, but pointing to something that isn't
|
||||
model.WritePointer(change, 2, 0xA2); // a pointer that isn't 4-byte aligned, pointing to something not 4-byte aligned
|
||||
var viewPort = new ViewPort(new LoadedFile("test.txt", data), model) { Width = 0x10, Height = 0x10 };
|
||||
|
||||
// got to 50 and write an anchor
|
||||
viewPort.SelectionStart = new Point(0x0, 0x5);
|
||||
viewPort.Edit("^test1 ");
|
||||
Assert.IsType<Pointer>(viewPort[0x3, 0x2].Format);
|
||||
Assert.Single(((Anchor)viewPort[0x0, 0x5].Format).Sources);
|
||||
|
||||
// go to 87 and write an anchor
|
||||
viewPort.SelectionStart = new Point(0x7, 0x8);
|
||||
viewPort.Edit("^test2 ");
|
||||
Assert.IsType<Pointer>(viewPort[0x0, 0x1].Format);
|
||||
Assert.Single(((Anchor)viewPort[0x7, 0x8].Format).Sources);
|
||||
|
||||
// go to A2 and write an anchor
|
||||
viewPort.SelectionStart = new Point(0x2, 0xA);
|
||||
viewPort.Edit("^test3 ");
|
||||
Assert.IsType<Pointer>(viewPort[0x2, 0x0].Format);
|
||||
Assert.Single(((Anchor)viewPort[0x2, 0xA].Format).Sources);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ namespace HavenSoft.Gen3Hex.WPF.Controls {
|
|||
}
|
||||
if (format is PCS pcs) children.AddRange(GetStringChildren(p));
|
||||
if (format is Pointer pointer) children.AddRange(GetPointerChildren(p));
|
||||
if (!(format is None || format is Undefined)) children.AddRange(GetClearFormattingChildren(p));
|
||||
} else {
|
||||
children.AddRange(GetSearchChildren(p));
|
||||
}
|
||||
|
|
@ -354,6 +355,15 @@ namespace HavenSoft.Gen3Hex.WPF.Controls {
|
|||
yield return CreateFollowLinkButton("Open in main tab", p);
|
||||
}
|
||||
|
||||
private IEnumerable<FrameworkElement> GetClearFormattingChildren(ModelPoint p) {
|
||||
yield return new Button {
|
||||
Content = new TextBlock { Text = "Clear Format" },
|
||||
}.SetEvent(ButtonBase.ClickEvent, (sender, e) => {
|
||||
((ViewPort)ViewPort).ClearFormat(p);
|
||||
recentMenu.IsOpen = false;
|
||||
});
|
||||
}
|
||||
|
||||
private Button CreateFollowLinkButton(string message, ModelPoint p) {
|
||||
return new Button {
|
||||
Content = new StackPanel {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user