mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-10-02 05:06:35 -05:00
Adding right click option to see if something is text
This commit is contained in:
@@ -124,13 +124,12 @@ namespace HavenSoft.HexManiac.Core.Models {
|
||||
}
|
||||
|
||||
private void WriteStringRuns(Dictionary<int, List<int>> pointersForDestination) {
|
||||
var destinations = pointersForDestination.Keys.OrderBy(i => i).GetEnumerator();
|
||||
destinations.MoveNext();
|
||||
var noDataChange = new NoDataChangeDeltaModel();
|
||||
foreach (var destination in pointersForDestination.Keys.OrderBy(i => i)) {
|
||||
var length = PCSString.ReadString(RawData, destination, false);
|
||||
if (length < 2) continue;
|
||||
if (GetNextRun(destination + 1).Start < destination + length) continue;
|
||||
ObserveRunWritten(new ModelDelta(), new PCSRun(destination, length, pointersForDestination[destination]));
|
||||
ObserveRunWritten(noDataChange, new PCSRun(destination, length, pointersForDestination[destination]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using static HavenSoft.HexManiac.Core.ICommandExtensions;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.ArrayRun;
|
||||
@@ -29,7 +30,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
private static readonly NotifyCollectionChangedEventArgs ResetArgs = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
|
||||
private readonly StubCommand
|
||||
clear = new StubCommand(),
|
||||
copy = new StubCommand();
|
||||
copy = new StubCommand(),
|
||||
isText = new StubCommand();
|
||||
|
||||
private HexElement[,] currentView;
|
||||
private bool exitEditEarly;
|
||||
@@ -270,6 +272,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
|
||||
public ICommand Copy => copy;
|
||||
public ICommand Clear => clear;
|
||||
public ICommand IsText => isText;
|
||||
|
||||
public HexElement this[Point p] => this[p.X, p.Y];
|
||||
|
||||
@@ -354,6 +357,9 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
if (usedHistory) UpdateToolsFromSelection(left);
|
||||
};
|
||||
|
||||
isText.CanExecute = CanAlwaysExecute;
|
||||
isText.Execute = IsTextExecuted;
|
||||
|
||||
save.CanExecute = arg => !history.IsSaved;
|
||||
save.Execute = arg => SaveExecuted((IFileSystem)arg);
|
||||
|
||||
@@ -518,20 +524,24 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
// for each of the results, we recognized it as text: see if we need to add a matching string run / pointers
|
||||
private int ConsiderResultsAsTextRuns(IEnumerable<int> searchResults) {
|
||||
int resultsRecognizedAsTextRuns = 0;
|
||||
var parallelLock = new object();
|
||||
|
||||
foreach (var result in searchResults) {
|
||||
Parallel.ForEach(searchResults, result => {
|
||||
// foreach (var result in searchResults) {
|
||||
var nextRun = Model.GetNextRun(result);
|
||||
if (nextRun.Start < result) continue;
|
||||
if (nextRun.Start == result && !(nextRun is NoInfoRun)) continue;
|
||||
if (nextRun.Start < result) return;
|
||||
if (nextRun.Start == result && !(nextRun is NoInfoRun)) return;
|
||||
var pointers = Model.SearchForPointersToAnchor(history.CurrentChange, result);
|
||||
if (pointers.Count == 0) continue;
|
||||
if (pointers.Count == 0) return;
|
||||
var length = PCSString.ReadString(Model, result, true);
|
||||
if (length < 1) continue;
|
||||
if (result + length > nextRun.Start && nextRun.Start != result) continue;
|
||||
if (length < 1) return;
|
||||
if (result + length > nextRun.Start && nextRun.Start != result) return;
|
||||
var newRun = new PCSRun(result, length, pointers);
|
||||
Model.ObserveAnchorWritten(history.CurrentChange, string.Empty, newRun);
|
||||
resultsRecognizedAsTextRuns++;
|
||||
}
|
||||
lock (parallelLock) {
|
||||
Model.ObserveAnchorWritten(history.CurrentChange, string.Empty, newRun);
|
||||
resultsRecognizedAsTextRuns++;
|
||||
}
|
||||
});
|
||||
|
||||
return resultsRecognizedAsTextRuns;
|
||||
}
|
||||
@@ -734,6 +744,35 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
return point;
|
||||
}
|
||||
|
||||
private void IsTextExecuted(object obj) {
|
||||
var selectionStart = scroll.ViewPointToDataIndex(selection.SelectionStart);
|
||||
var selectionEnd = scroll.ViewPointToDataIndex(selection.SelectionEnd);
|
||||
var left = Math.Min(selectionStart, selectionEnd);
|
||||
var length = Math.Abs(selectionEnd - selectionStart) + 1;
|
||||
while (Model[left] != 0xFF && PCSString.PCS[Model[left]] != null) { left--; length++; }
|
||||
left++; length--;
|
||||
while (true) {
|
||||
var run = Model.GetNextRun(left);
|
||||
if (run.Start >= left) break;
|
||||
length -= left - run.Start;
|
||||
left = run.Start + run.Length;
|
||||
}
|
||||
var startPaces = new List<int>();
|
||||
while (length > 0) {
|
||||
startPaces.Add(left);
|
||||
while (Model[left] != 0xFF) { left++; length--; }
|
||||
left++; length--;
|
||||
var run = Model.GetNextRun(left);
|
||||
if (!(run is NoInfoRun)) break;
|
||||
}
|
||||
var foundCount = ConsiderResultsAsTextRuns(startPaces);
|
||||
if (foundCount == 0) {
|
||||
OnError?.Invoke(this, "Failed to automatically find text at that location.");
|
||||
} else {
|
||||
RefreshBackingData();
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldAcceptInput(ref Point point, ref HexElement element, char input) {
|
||||
var underEdit = element.Format as UnderEdit;
|
||||
var innerFormat = underEdit?.OriginalFormat ?? element.Format;
|
||||
|
||||
@@ -419,5 +419,23 @@ namespace HavenSoft.HexManiac.Tests {
|
||||
Assert.NotEqual("anchor", ((Anchor)viewPort[0, 1].Format).Name);
|
||||
Assert.Single(messages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanUseViewPortToAutoFindTextWithoutKnowingAboutPointersToIt() {
|
||||
var text = PCSString.Convert("This is some text.");
|
||||
var buffer = Enumerable.Range(0, 0x200).Select(i => (byte)0xFF).ToArray();
|
||||
text.CopyTo(buffer, 0x10);
|
||||
var model = new PokemonModel(buffer);
|
||||
model.WritePointer(new ModelDelta(), 0x00, 0x10);
|
||||
|
||||
var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 };
|
||||
viewPort.SelectionStart = new Point(3, 1); // just a random byte in the middle of the text
|
||||
var errors = new List<string>();
|
||||
viewPort.OnError += (sender, e) => errors.Add(e);
|
||||
|
||||
viewPort.IsText.Execute(); // this line should find the start of the text and add a run, even with no pointer to it
|
||||
|
||||
Assert.IsType<PCS>(viewPort[3, 1].Format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,6 +249,7 @@ namespace HavenSoft.HexManiac.WPF.Controls {
|
||||
if (format is PCS pcs) children.AddRange(GetStringChildren(p));
|
||||
if (ViewPort.IsTable(p)) children.AddRange(GetTableChildren(p));
|
||||
if (format is Pointer pointer) children.AddRange(GetPointerChildren(p));
|
||||
if (format is None none) children.AddRange(GetNoneChildren(p));
|
||||
if (editableViewPort.FormattedDataIsSelected) children.AddRange(GetClearFormattingChildren(p));
|
||||
} else {
|
||||
children.AddRange(GetSearchChildren(p));
|
||||
@@ -410,6 +411,15 @@ namespace HavenSoft.HexManiac.WPF.Controls {
|
||||
yield return CreateFollowLinkButton("Follow Pointer", p);
|
||||
}
|
||||
|
||||
private IEnumerable<FrameworkElement> GetNoneChildren(ModelPoint p) {
|
||||
yield return new Button {
|
||||
Content = new TextBlock { Text = "This is Text" },
|
||||
}.SetEvent(ButtonBase.ClickEvent, (sender, e) => {
|
||||
((ViewPort)ViewPort).IsText.Execute();
|
||||
recentMenu.IsOpen = false;
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerable<FrameworkElement> GetTableChildren(ModelPoint p) {
|
||||
yield return new Button {
|
||||
Content = new TextBlock { Text = "Open in Table Tool" },
|
||||
|
||||
Reference in New Issue
Block a user