From 11cbc1ba1e1fb13bcaadeb7d6e681eb9fbca3446 Mon Sep 17 00:00:00 2001 From: Benjamin Popp Date: Sat, 26 Oct 2019 15:05:32 -0500 Subject: [PATCH] Add a search field to the text tool The unit test and search logic implementation were actually pretty simple. However, WPF TextBox's don't natively support a way to show text highlight when the textbox doesn't have focus... so I had to implemnet my own focus. I did this by wrapping the TextBox in a Grid so I could overlay a Rectangle that uses the same highlight color. See TabView.xaml.cs for all the mathy bits. --- .../ViewModels/Tools/PCSTool.cs | 26 ++++++- src/HexManiac.Tests/ToolTests.cs | 17 +++++ src/HexManiac.WPF/Controls/TabView.xaml | 27 +++++-- src/HexManiac.WPF/Controls/TabView.xaml.cs | 76 ++++++++++++++++++- 4 files changed, 137 insertions(+), 9 deletions(-) diff --git a/src/HexManiac.Core/ViewModels/Tools/PCSTool.cs b/src/HexManiac.Core/ViewModels/Tools/PCSTool.cs index 3a2bc969..07cd3468 100644 --- a/src/HexManiac.Core/ViewModels/Tools/PCSTool.cs +++ b/src/HexManiac.Core/ViewModels/Tools/PCSTool.cs @@ -13,6 +13,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { private readonly IToolTrayViewModel runner; private readonly StubCommand checkIsText = new StubCommand(), + search = new StubCommand(), insertText = new StubCommand(); // if we're in the middle of updating ourselves, we may notify changes to other controls. @@ -37,16 +38,24 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { } } + private string searchText; + public string SearchText { + get => searchText; + set => TryUpdate(ref searchText, value); + } + public ICommand CheckIsText => checkIsText; + public ICommand Search => search; public ICommand InsertText => insertText; - private bool showMessage; + private bool showMessage = true; public bool ShowMessage { get => showMessage; set { if (TryUpdate(ref showMessage, value)) { checkIsText.CanExecuteChanged?.Invoke(checkIsText, EventArgs.Empty); insertText.CanExecuteChanged?.Invoke(checkIsText, EventArgs.Empty); + search.CanExecuteChanged?.Invoke(checkIsText, EventArgs.Empty); } } } @@ -129,6 +138,21 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { Enabled = true; ShowMessage = false; }; + search.CanExecute = arg => !ShowMessage; + search.Execute = arg => { + var target = searchText.ToLower(); + if (target.Length == 0) return; + var content = Content.ToLower(); + var start = Math.Min(Content.Length - target.Length, contentIndex); + + var index = content.Substring(start + 1).IndexOf(target); + if (index < 0) index = content.IndexOf(target); + else index += start + 1; + + if (index < 0) return; + ContentIndex = index; + ContentSelectionLength = target.Length; + }; } public void RefreshContentAtAddress() { diff --git a/src/HexManiac.Tests/ToolTests.cs b/src/HexManiac.Tests/ToolTests.cs index 270ecf9d..0bf776b8 100644 --- a/src/HexManiac.Tests/ToolTests.cs +++ b/src/HexManiac.Tests/ToolTests.cs @@ -494,6 +494,23 @@ namespace HavenSoft.HexManiac.Tests { Assert.Equal("000030", test.ViewPort.Headers[0]); } + [Fact] + public void TextToolSearchTest() { + var test = new BaseViewModelTestClass(); + test.ViewPort.Edit("FF @00 ^text\"\" Hello World Worble!"); + test.ViewPort.SelectionStart = new Point(); + var tool = test.ViewPort.Tools.StringTool; + + tool.SearchText = "wor"; + tool.Search.Execute(); + Assert.Equal(6, tool.ContentIndex); + Assert.Equal(3, tool.ContentSelectionLength); + + tool.Search.Execute(); + Assert.Equal(12, tool.ContentIndex); + Assert.Equal(3, tool.ContentSelectionLength); + } + private static readonly ThumbParser parser; static ToolTests(){ parser = new ThumbParser(File.ReadAllLines("Models/Code/armReference.txt")); diff --git a/src/HexManiac.WPF/Controls/TabView.xaml b/src/HexManiac.WPF/Controls/TabView.xaml index 83e6d318..1a44f5cb 100644 --- a/src/HexManiac.WPF/Controls/TabView.xaml +++ b/src/HexManiac.WPF/Controls/TabView.xaml @@ -4,7 +4,8 @@ xmlns:hsv="clr-namespace:HavenSoft.HexManiac.WPF.Resources" xmlns:hsg3hvmtr="clr-namespace:HavenSoft.HexManiac.Core.ViewModels.Tools;assembly=HexManiac.Core" xmlns:hsg3ww="clr-namespace:HavenSoft.HexManiac.WPF.Windows" - xmlns:hsg3hv="clr-namespace:HavenSoft.HexManiac.WPF.Controls"> + xmlns:hsg3hv="clr-namespace:HavenSoft.HexManiac.WPF.Controls" + DataContextChanged="HandleDataContextChanged"> @@ -85,10 +86,26 @@