mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-10-02 05:06:35 -05:00
@@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28010.2016
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gen3Hex.WPF", "src\Gen3Hex.WPF\Gen3Hex.WPF.csproj", "{386DC8E2-BABC-475C-94B6-37B3986F5F4C}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexManiac.WPF", "src\HexManiac.WPF\HexManiac.WPF.csproj", "{386DC8E2-BABC-475C-94B6-37B3986F5F4C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gen3Hex.Core", "src\Gen3Hex.Core\Gen3Hex.Core.csproj", "{B7B9D932-4271-493D-AADD-6CF147C91373}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexManiac.Core", "src\HexManiac.Core\HexManiac.Core.csproj", "{B7B9D932-4271-493D-AADD-6CF147C91373}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gen3Hex.Tests", "src\Gen3Hex.Tests\Gen3Hex.Tests.csproj", "{B6A52732-E0F8-466D-8E29-664C797A21FA}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexManiac.Tests", "src\HexManiac.Tests\HexManiac.Tests.csproj", "{B6A52732-E0F8-466D-8E29-664C797A21FA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -1,3 +0,0 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("Gen3Hex.Core")]
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 116 KiB |
3
src/HexManiac.Core/AssemblyInfo.cs
Normal file
3
src/HexManiac.Core/AssemblyInfo.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("HexManiac.Core")]
|
||||
@@ -6,8 +6,8 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{B7B9D932-4271-493D-AADD-6CF147C91373}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>HavenSoft.Gen3Hex.Core</RootNamespace>
|
||||
<AssemblyName>Gen3Hex.Core</AssemblyName>
|
||||
<RootNamespace>HavenSoft.HexManiac.Core</RootNamespace>
|
||||
<AssemblyName>HexManiac.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
@@ -47,6 +47,7 @@
|
||||
<Compile Include="Models\AutoSearchModel.cs" />
|
||||
<Compile Include="Models\ErrorInfo.cs" />
|
||||
<Compile Include="Models\IDataModel.cs" />
|
||||
<Compile Include="Models\Runs\AsciiRun.cs" />
|
||||
<Compile Include="Models\Runs\IFormattedRun.cs" />
|
||||
<Compile Include="Models\ModelDelta.cs" />
|
||||
<Compile Include="Models\Runs\PCSRun.cs" />
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core {
|
||||
namespace HavenSoft.HexManiac.Core {
|
||||
public static class ICommandExtensions {
|
||||
/// <summary>
|
||||
/// Runs execute on the command with a null parameter.
|
||||
@@ -1,8 +1,8 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using System.Linq;
|
||||
using static HavenSoft.Gen3Hex.Core.Models.Runs.ArrayRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.ArrayRun;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public class AutoSearchModel : PokemonModel {
|
||||
public const string
|
||||
Ruby = "AXVE",
|
||||
@@ -11,19 +11,44 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
FireRed = "BPRE",
|
||||
LeafGreen = "BPGE";
|
||||
|
||||
private readonly string gameCode;
|
||||
private readonly ModelDelta noChangeDelta = new NoDataChangeDeltaModel();
|
||||
|
||||
/// <summary>
|
||||
/// The first 0x100 bytes of the GBA rom is always the header.
|
||||
/// The next 0x100 bytes contains some tables and some startup code, but nothing interesting to point to.
|
||||
/// Choosing 0x200 might prevent us from seeing an actual anchor, but it will also remove a bunch
|
||||
/// of false positives and keep us from getting conflicts with the RomName (see DecodeHeader).
|
||||
/// </summary>
|
||||
public override int EarliestAllowedAnchor => 0x200;
|
||||
|
||||
public AutoSearchModel(byte[] data, StoredMetadata metadata = null) : base(data, metadata) {
|
||||
if (metadata != null) return;
|
||||
|
||||
var noChangeDelta = new NoDataChangeDeltaModel();
|
||||
|
||||
ClearFormat(noChangeDelta, -1, 0x101); // starting before the beginning to clear the anchor at the very start
|
||||
|
||||
var gameCode = string.Concat(Enumerable.Range(0xAC, 4).Select(i => ((char)data[i]).ToString()));
|
||||
gameCode = string.Concat(Enumerable.Range(0xAC, 4).Select(i => ((char)data[i]).ToString()));
|
||||
|
||||
// in vanilla emerald, this pointer isn't four-byte aligned
|
||||
// it's at the very front of the ROM, so if there's no metadata we can be pretty sure that the pointer is still there
|
||||
if (gameCode == Emerald && data[0x1C3] == 0x08) ObserveRunWritten(noChangeDelta, new PointerRun(0x1C0));
|
||||
|
||||
var gamesToDecode = new[] { Ruby, Sapphire, Emerald, FireRed, LeafGreen };
|
||||
if (gamesToDecode.Contains(gameCode)) {
|
||||
DecodeHeader();
|
||||
DecodeNameArrays();
|
||||
}
|
||||
}
|
||||
|
||||
private void DecodeHeader() {
|
||||
ObserveAnchorWritten(noChangeDelta, "GameTitle", new AsciiRun(0xA0, 12));
|
||||
ObserveAnchorWritten(noChangeDelta, "GameCode", new AsciiRun(0xAC, 4));
|
||||
ObserveAnchorWritten(noChangeDelta, "MakerCode", new AsciiRun(0xB0, 2));
|
||||
|
||||
if (gameCode != Ruby && gameCode != Sapphire) {
|
||||
ObserveAnchorWritten(noChangeDelta, "RomName", new AsciiRun(0x108, 0x20));
|
||||
}
|
||||
}
|
||||
|
||||
private void DecodeNameArrays() {
|
||||
// pokenames
|
||||
if (TrySearch(this, "[name\"\"11]", out var pokenames)) {
|
||||
ObserveAnchorWritten(noChangeDelta, "pokenames", pokenames);
|
||||
@@ -1,3 +1,3 @@
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public enum Direction { Left, Right, Up, Down }
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public class ErrorInfo : IEquatable<ErrorInfo> {
|
||||
public static ErrorInfo NoError { get; } = new ErrorInfo(null);
|
||||
public bool HasError { get; }
|
||||
@@ -1,11 +1,11 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public interface IDataModel : IReadOnlyList<byte> {
|
||||
byte[] RawData { get; }
|
||||
new byte this[int index] { get; set; }
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public interface IFileSystem {
|
||||
string CopyText { get; set; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public class LoadedFile {
|
||||
public string Name { get; }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
/// <summary>
|
||||
/// Represents a single conceptual change in the loaded data, including
|
||||
/// editing data, adding / removing formats / format names,
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public class PCSString {
|
||||
public static IReadOnlyList<string> PCS;
|
||||
public static IReadOnlyList<byte> Newlines;
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public struct Point : IEquatable<Point> {
|
||||
public int X { get; }
|
||||
public int Y { get; }
|
||||
@@ -1,15 +1,16 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static HavenSoft.Gen3Hex.Core.Models.Runs.ArrayRun;
|
||||
using static HavenSoft.Gen3Hex.Core.Models.Runs.BaseRun;
|
||||
using static HavenSoft.Gen3Hex.Core.Models.Runs.PCSRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.ArrayRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.AsciiRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.BaseRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.PCSRun;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public class PokemonModel : BaseModel {
|
||||
// list of runs, in sorted address order. Includes no names
|
||||
private readonly List<IFormattedRun> runs = new List<IFormattedRun>();
|
||||
@@ -24,6 +25,8 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
private readonly Dictionary<string, List<int>> unmappedNameToSources = new Dictionary<string, List<int>>();
|
||||
private readonly Dictionary<int, string> sourceToUnmappedName = new Dictionary<int, string>();
|
||||
|
||||
public virtual int EarliestAllowedAnchor => 0;
|
||||
|
||||
#region Constructor
|
||||
|
||||
public PokemonModel(byte[] data, StoredMetadata metadata = null) : base(data) {
|
||||
@@ -50,13 +53,34 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds pointers based on Heuristics.
|
||||
/// This is definitely wrong, but it's pretty good.
|
||||
/// </summary>
|
||||
private void SearchForPointers(Dictionary<int, List<int>> pointersForDestination, SortedList<int, int> destinationForSource) {
|
||||
// pointers must be 4-byte aligned
|
||||
for (int i = 0; i < RawData.Length - 3; i += 4) {
|
||||
|
||||
// pointers must end in 08 or 09
|
||||
if (RawData[i + 3] != 0x08 && RawData[i + 3] != 0x09) continue;
|
||||
|
||||
// pointers must point to locations that are 4-byte aligned
|
||||
if (RawData[i] % 4 != 0) continue;
|
||||
var source = i;
|
||||
var destination = ReadPointer(i);
|
||||
|
||||
// pointers must point into the data
|
||||
if (destination >= RawData.Length) continue;
|
||||
|
||||
// pointers must not point at the header
|
||||
if (destination < EarliestAllowedAnchor) continue;
|
||||
|
||||
// pointers must point at something useful, not just a bunch of FF
|
||||
bool pointsToManyFF = true;
|
||||
for (int j = 0; j < 4 && pointsToManyFF && destination + j < RawData.Length; j++) pointsToManyFF = RawData[destination + j] == 0xFF;
|
||||
if (pointsToManyFF) continue;
|
||||
|
||||
// we found a pointer!
|
||||
if (!pointersForDestination.ContainsKey(destination)) pointersForDestination[destination] = new List<int>();
|
||||
pointersForDestination[destination].Add(source);
|
||||
destinationForSource.Add(source, destination);
|
||||
@@ -279,6 +303,8 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
ClearFormat(changeToken, run.Start, run.Length);
|
||||
}
|
||||
|
||||
var existingRun = (index >= 0 && index < runs.Count) ? runs[index] : null;
|
||||
|
||||
if (anchorForAddress.TryGetValue(location, out string oldAnchorName)) {
|
||||
anchorForAddress.Remove(location);
|
||||
addressForAnchor.Remove(oldAnchorName);
|
||||
@@ -296,7 +322,8 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
changeToken.AddName(location, anchorName);
|
||||
}
|
||||
|
||||
var sources = GetSourcesPointingToNewAnchor(changeToken, anchorName);
|
||||
var seakPointers = existingRun?.PointerSources == null || existingRun?.Start != location;
|
||||
var sources = GetSourcesPointingToNewAnchor(changeToken, anchorName, seakPointers);
|
||||
var newRun = run.MergeAnchor(sources);
|
||||
ObserveRunWritten(changeToken, newRun);
|
||||
}
|
||||
@@ -585,13 +612,17 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
private static (string, string) SplitNameAndFormat(string text) {
|
||||
var name = text.Substring(1).Trim();
|
||||
string format = string.Empty;
|
||||
int split = -1;
|
||||
|
||||
if (name.Contains(ArrayStart)) {
|
||||
var split = name.IndexOf(ArrayStart);
|
||||
format = name.Substring(split);
|
||||
name = name.Substring(0, split);
|
||||
split = name.IndexOf(ArrayStart);
|
||||
} else if (name.Contains(StringDelimeter)) {
|
||||
var split = name.IndexOf(StringDelimeter);
|
||||
split = name.IndexOf(StringDelimeter);
|
||||
} else if (name.Contains(StreamDelimeter)) {
|
||||
split = name.IndexOf(StreamDelimeter);
|
||||
}
|
||||
|
||||
if (split != -1) {
|
||||
format = name.Substring(split);
|
||||
name = name.Substring(0, split);
|
||||
}
|
||||
@@ -610,6 +641,12 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
return new ErrorInfo($"Format was specified as a string, but a string would overlap the next anchor.");
|
||||
}
|
||||
run = new PCSRun(dataIndex, length);
|
||||
} else if (format.StartsWith(StreamDelimeter + "asc" + StreamDelimeter)) {
|
||||
if (int.TryParse(format.Substring(5), out var length)) {
|
||||
run = new AsciiRun(dataIndex, length);
|
||||
} else {
|
||||
return new ErrorInfo($"Ascii runs must include a length.");
|
||||
}
|
||||
} else if (TryParse(model, format, dataIndex, null, out var arrayRun)) {
|
||||
run = arrayRun;
|
||||
} else if (format != string.Empty) {
|
||||
@@ -621,7 +658,7 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
|
||||
private static ErrorInfo ValidateAnchorNameAndFormat(IDataModel model, IFormattedRun runToWrite, string name, string format, int dataIndex) {
|
||||
var existingRun = model.GetNextRun(dataIndex);
|
||||
var nextRun = existingRun.Start > dataIndex ? existingRun : model.GetNextRun(existingRun.Start + existingRun.Length);
|
||||
var nextRun = existingRun.Start > dataIndex ? existingRun : model.GetNextRun(existingRun.Start + Math.Max(existingRun.Length, 1));
|
||||
|
||||
if (name.ToLower() == "null") {
|
||||
return new ErrorInfo("'null' is a reserved word and cannot be used as an anchor name.");
|
||||
@@ -664,9 +701,15 @@ namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
/// <returns>
|
||||
/// The list of sources that point at the new anchor
|
||||
/// </returns>
|
||||
private IReadOnlyList<int> GetSourcesPointingToNewAnchor(ModelDelta changeToken, string anchorName) {
|
||||
private IReadOnlyList<int> GetSourcesPointingToNewAnchor(ModelDelta changeToken, string anchorName, bool seakPointers) {
|
||||
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 thinks there's something pointing here
|
||||
if (seakPointers) return SearchForPointersToAnchor(changeToken, location);
|
||||
return new List<int>();
|
||||
}
|
||||
|
||||
foreach (var source in sources) {
|
||||
var index = BinarySearch(source);
|
||||
@@ -681,6 +724,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 (index < runs.Count && 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) {
|
||||
@@ -740,6 +804,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;
|
||||
@@ -1,10 +1,10 @@
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models.Runs {
|
||||
namespace HavenSoft.HexManiac.Core.Models.Runs {
|
||||
public enum ElementContentType {
|
||||
Unknown,
|
||||
PCS,
|
||||
22
src/HexManiac.Core/Models/Runs/AsciiRun.cs
Normal file
22
src/HexManiac.Core/Models/Runs/AsciiRun.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace HavenSoft.HexManiac.Core.Models.Runs {
|
||||
public class AsciiRun : BaseRun {
|
||||
public const char StreamDelimeter = '`';
|
||||
|
||||
public override int Length { get; }
|
||||
|
||||
public override string FormatString => "`asc`" + Length;
|
||||
|
||||
public AsciiRun(int start, int length, IReadOnlyList<int> pointerSources = null) : base(start, pointerSources) => Length = length;
|
||||
|
||||
public override IDataFormat CreateDataFormat(IDataModel data, int index) {
|
||||
return new Ascii(Start, index - Start, (char)data[index]);
|
||||
}
|
||||
|
||||
protected override IFormattedRun Clone(IReadOnlyList<int> newPointerSources) {
|
||||
return new AsciiRun(Start, Length, newPointerSources);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models.Runs {
|
||||
namespace HavenSoft.HexManiac.Core.Models.Runs {
|
||||
public interface IFormattedRun {
|
||||
int Start { get; }
|
||||
int Length { get; }
|
||||
@@ -1,7 +1,7 @@
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models.Runs {
|
||||
namespace HavenSoft.HexManiac.Core.Models.Runs {
|
||||
public class PCSRun : BaseRun {
|
||||
public const char StringDelimeter = '"';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models.Runs {
|
||||
namespace HavenSoft.HexManiac.Core.Models.Runs {
|
||||
public class PointerRun : BaseRun {
|
||||
public const char PointerStart = '<';
|
||||
public const char PointerEnd = '>';
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public interface ISearchByte {
|
||||
bool Match(byte value);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.Models {
|
||||
namespace HavenSoft.HexManiac.Core.Models {
|
||||
public class StoredMetadata {
|
||||
public IReadOnlyList<StoredAnchor> NamedAnchors { get; }
|
||||
public IReadOnlyList<StoredUnmappedPointers> UnmappedPointers { get; }
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core {
|
||||
namespace HavenSoft.HexManiac.Core {
|
||||
public static class NumericExtensions {
|
||||
public static T LimitToRange<T>(this T value, T lower, T upper) where T : IComparable<T> {
|
||||
if (upper.CompareTo(lower) < 0) throw new ArgumentException($"upper value {upper} is less than lower value {lower}");
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
/// <summary>
|
||||
/// Represents a history of changes that can undo / redo.
|
||||
/// The change can be reperesented by any class with an empty constructor.
|
||||
@@ -1,6 +1,6 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
/// <summary>
|
||||
/// exactly replaces a ViewPort, except that it also has a known parent view
|
||||
/// </summary>
|
||||
@@ -5,7 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels.DataFormats {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels.DataFormats {
|
||||
public interface IDataFormat : IEquatable<IDataFormat> {
|
||||
void Visit(IDataFormatVisitor visitor, byte data);
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels.DataFormats {
|
||||
void Visit(PCS pcs, byte data);
|
||||
void Visit(EscapedPCS pcs, byte data);
|
||||
void Visit(ErrorPCS pcs, byte data);
|
||||
void Visit(Ascii ascii, byte data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -154,4 +155,19 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels.DataFormats {
|
||||
|
||||
public void Visit(IDataFormatVisitor visitor, byte data) => visitor.Visit(this, data);
|
||||
}
|
||||
|
||||
public class Ascii : IDataFormat {
|
||||
public int Source { get; }
|
||||
public int Position { get; }
|
||||
public char ThisCharacter { get; }
|
||||
|
||||
public Ascii(int source, int position, char value) => (Source, Position, ThisCharacter) = (source, position, value);
|
||||
|
||||
public bool Equals(IDataFormat other) {
|
||||
if (!(other is Ascii ascii)) return false;
|
||||
return ascii.Source == Source && ascii.Position == Position && ascii.ThisCharacter == ThisCharacter;
|
||||
}
|
||||
|
||||
public void Visit(IDataFormatVisitor visitor, byte data) => visitor.Visit(this, data);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@@ -6,10 +6,11 @@ using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using static HavenSoft.Gen3Hex.Core.ICommandExtensions;
|
||||
using static HavenSoft.HexManiac.Core.ICommandExtensions;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public class EditorViewModel : ViewModelCore, IEnumerable<ITabContent>, INotifyCollectionChanged {
|
||||
private const int MaxReasonableResults = 200; // limit for performance reasons
|
||||
|
||||
private readonly IFileSystem fileSystem;
|
||||
private readonly List<ITabContent> tabs;
|
||||
@@ -43,7 +44,6 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
toggleMatrix = new StubCommand();
|
||||
|
||||
private readonly Dictionary<Func<ITabContent, ICommand>, EventHandler> forwardExecuteChangeNotifications;
|
||||
|
||||
private (IViewPort tab, int)[] recentFindResults = new (IViewPort, int)[0];
|
||||
private int currentFindResultIndex;
|
||||
|
||||
@@ -374,6 +374,11 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
return;
|
||||
}
|
||||
|
||||
if (results.Count > MaxReasonableResults) {
|
||||
ErrorMessage = $"Found {results.Count} results: please refine your search.";
|
||||
return;
|
||||
}
|
||||
|
||||
var newTab = new SearchResultsViewPort(search);
|
||||
foreach (var (tab, offset) in results) {
|
||||
newTab.Add(tab.CreateChildView(offset));
|
||||
@@ -2,9 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using static HavenSoft.Gen3Hex.Core.ICommandExtensions;
|
||||
using static HavenSoft.HexManiac.Core.ICommandExtensions;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public class GotoControlViewModel : ViewModelCore {
|
||||
private readonly IViewPort viewPort;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public class HexElement {
|
||||
public static readonly HexElement Undefined = new HexElement(0, DataFormats.Undefined.Instance);
|
||||
public byte Value { get; }
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public interface IChildViewPort : IViewPort {
|
||||
IViewPort Parent { get; }
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
/// <summary>
|
||||
/// Each command expects an IFileSystem as its Command Parameter.
|
||||
/// </summary>
|
||||
@@ -1,11 +1,11 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.Tools;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Tools;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public interface IViewPort : ITabContent, INotifyCollectionChanged {
|
||||
string FileName { get; } // Name is dispayed in a tab. FileName lets us know when to call 'ConsiderReload'
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public class ScrollRegion : ViewModelCore {
|
||||
public static readonly IReadOnlyDictionary<Direction, Point> DirectionToDif = new Dictionary<Direction, Point> {
|
||||
{ Direction.Up, new Point( 0,-1) },
|
||||
@@ -1,5 +1,5 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.Tools;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Tools;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -7,7 +7,7 @@ using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public class SearchResultsViewPort : ViewModelCore, IViewPort {
|
||||
private readonly StubCommand scroll, close;
|
||||
private readonly List<IChildViewPort> children = new List<IChildViewPort>();
|
||||
@@ -1,13 +1,13 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public class Selection : ViewModelCore {
|
||||
|
||||
private readonly IDataModel model;
|
||||
@@ -97,7 +97,11 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
if (anchor != Pointer.NULL) {
|
||||
GotoAddress(anchor);
|
||||
} else if (int.TryParse(address, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out int result)) {
|
||||
GotoAddress(result);
|
||||
if (result > Scroll.DataLength || result < 0) {
|
||||
OnError?.Invoke(this, $"Address {result:X2} is not within the size of the data.");
|
||||
} else {
|
||||
GotoAddress(result);
|
||||
}
|
||||
} else {
|
||||
OnError?.Invoke(this, $"Unable to goto address '{address}'");
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@@ -6,7 +6,7 @@ using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels.Tools {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
|
||||
public interface IToolTrayViewModel : IReadOnlyList<IToolViewModel>, INotifyPropertyChanged {
|
||||
int SelectedIndex { get; set; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels.Tools {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
|
||||
public interface IToolViewModel : INotifyPropertyChanged {
|
||||
string Name { get; }
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels.Tools {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
|
||||
public class PCSTool : ViewModelCore, IToolViewModel {
|
||||
private readonly IDataModel model;
|
||||
private readonly Selection selection;
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public class ViewModelCore : INotifyPropertyChanged {
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.Tools;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Tools;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -12,13 +12,14 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using static HavenSoft.Gen3Hex.Core.ICommandExtensions;
|
||||
using static HavenSoft.Gen3Hex.Core.Models.Runs.ArrayRun;
|
||||
using static HavenSoft.Gen3Hex.Core.Models.Runs.BaseRun;
|
||||
using static HavenSoft.Gen3Hex.Core.Models.Runs.PCSRun;
|
||||
using static HavenSoft.Gen3Hex.Core.Models.Runs.PointerRun;
|
||||
using static HavenSoft.HexManiac.Core.ICommandExtensions;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.ArrayRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.AsciiRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.BaseRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.PCSRun;
|
||||
using static HavenSoft.HexManiac.Core.Models.Runs.PointerRun;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
/// <summary>
|
||||
/// A range of visible data that should be displayed.
|
||||
/// </summary>
|
||||
@@ -327,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) {
|
||||
@@ -674,6 +681,10 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
return AllHexCharacters.Contains(input);
|
||||
}
|
||||
|
||||
if (innerFormat is Ascii) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input == PointerStart) {
|
||||
// pointer edits are 4 bytes long
|
||||
if(!TryCoerceSelectionToStartOfPointer(ref point, ref element)) PrepareForMultiSpaceEdit(point, 4);
|
||||
@@ -682,7 +693,7 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
} else if (underEdit.CurrentText.StartsWith(PointerStart.ToString())) {
|
||||
return char.IsLetterOrDigit(input) || input == PointerEnd;
|
||||
} else if (underEdit.CurrentText.StartsWith(AnchorStart.ToString())) {
|
||||
return char.IsLetterOrDigit(input) || char.IsWhiteSpace(input) || input == ArrayStart || input == ArrayEnd || input == StringDelimeter;
|
||||
return char.IsLetterOrDigit(input) || char.IsWhiteSpace(input) || input == ArrayStart || input == ArrayEnd || input == StringDelimeter || input == StreamDelimeter;
|
||||
} else if (underEdit.OriginalFormat is Anchor anchorFormat && anchorFormat.OriginalFormat is PCS) {
|
||||
if (input == StringDelimeter) return true;
|
||||
// if this is the start of a string (as noted by the anchor), crop off the leading " before trying to convert to a byte
|
||||
@@ -764,10 +775,13 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
return true;
|
||||
}
|
||||
|
||||
PCS stringFormat = null;
|
||||
if (underEdit.OriginalFormat is Anchor anchorFormat) stringFormat = anchorFormat.OriginalFormat as PCS;
|
||||
stringFormat = stringFormat ?? underEdit.OriginalFormat as PCS;
|
||||
if (stringFormat != null) {
|
||||
var originalFormat = underEdit.OriginalFormat;
|
||||
if (originalFormat is Anchor) originalFormat = ((Anchor)originalFormat).OriginalFormat;
|
||||
if (originalFormat is Ascii) {
|
||||
CompleteAsciiEdit(point, underEdit.CurrentText);
|
||||
return true;
|
||||
}
|
||||
if (originalFormat is PCS stringFormat) {
|
||||
var currentText = underEdit.CurrentText;
|
||||
if (currentText.StartsWith(StringDelimeter.ToString())) currentText = currentText.Substring(1);
|
||||
if (stringFormat.Position != 0 && underEdit.CurrentText == StringDelimeter.ToString()) {
|
||||
@@ -790,6 +804,17 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CompleteAsciiEdit(Point point, string currentText) {
|
||||
var memoryLocation = scroll.ViewPointToDataIndex(point);
|
||||
var editFormat = (UnderEdit)currentView[point.X, point.Y].Format;
|
||||
var asciiFormat = (Ascii)editFormat.OriginalFormat;
|
||||
var content = (byte)currentText[0];
|
||||
|
||||
history.CurrentChange.ChangeData(Model, memoryLocation, content);
|
||||
currentView[point.X, point.Y] = new HexElement(content, new Ascii(asciiFormat.Source, asciiFormat.Position, currentText[0]));
|
||||
SilentScroll(memoryLocation + 1);
|
||||
}
|
||||
|
||||
private void CompleteArrayExtension(ArrayRun arrayRun) {
|
||||
var newRun = (ArrayRun)Model.RelocateForExpansion(history.CurrentChange, arrayRun, arrayRun.Length + arrayRun.ElementLength);
|
||||
if (newRun != arrayRun) {
|
||||
@@ -1079,6 +1104,8 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
public void Visit(EscapedPCS pcs, byte data) => Visit((None)null, data);
|
||||
|
||||
public void Visit(ErrorPCS pcs, byte data) => Visit((None)null, data);
|
||||
|
||||
public void Visit(Ascii ascii, byte data) => Result = ((char)data).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1115,6 +1142,8 @@ namespace HavenSoft.Gen3Hex.Core.ViewModels {
|
||||
public void Visit(EscapedPCS pcs, byte data) => currentChange.ChangeData(buffer, index, 0xFF);
|
||||
|
||||
public void Visit(ErrorPCS pcs, byte data) => currentChange.ChangeData(buffer, index, 0xFF);
|
||||
|
||||
public void Visit(Ascii ascii, byte data) => currentChange.ChangeData(buffer, index, 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class ArrayRunTests {
|
||||
[Fact]
|
||||
public void CanParseStringArrayRun() {
|
||||
46
src/HexManiac.Tests/AsciiRunTests.cs
Normal file
46
src/HexManiac.Tests/AsciiRunTests.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class AsciiRunTests {
|
||||
[Fact]
|
||||
public void CanCreateAsciiRun() {
|
||||
var buffer = new byte[0x200];
|
||||
var model = new PokemonModel(buffer);
|
||||
model[0x10] = (byte)'a';
|
||||
model[0x11] = (byte)'b';
|
||||
model[0x12] = (byte)'c';
|
||||
model[0x13] = (byte)'d';
|
||||
|
||||
var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 };
|
||||
viewPort.SelectionStart = new Point(0, 1);
|
||||
viewPort.Edit("^data`asc`4 ");
|
||||
|
||||
var format = (Ascii)viewPort[1, 1].Format;
|
||||
Assert.Equal('b', format.ThisCharacter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanEditAsciiRun() {
|
||||
var buffer = new byte[0x200];
|
||||
var model = new PokemonModel(buffer);
|
||||
model[0x10] = (byte)'a';
|
||||
model[0x11] = (byte)'b';
|
||||
model[0x12] = (byte)'c';
|
||||
model[0x13] = (byte)'d';
|
||||
|
||||
model.ObserveRunWritten(new ModelDelta(), new AsciiRun(0x10, 4));
|
||||
|
||||
var viewPort = new ViewPort(new LoadedFile("file.txt", buffer), model) { Width = 0x10, Height = 0x10 };
|
||||
viewPort.SelectionStart = new Point(1, 1);
|
||||
viewPort.Edit("3");
|
||||
|
||||
var format = (Ascii)viewPort[1, 1].Format;
|
||||
Assert.Equal('3', format.ThisCharacter);
|
||||
Assert.Equal(new Point(2, 1), viewPort.SelectionStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class ChangeHistoryTests {
|
||||
|
||||
private readonly ChangeHistory<List<int>> history;
|
||||
@@ -1,11 +1,11 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class FindTests {
|
||||
[Fact]
|
||||
public void FindCanFindSingle() {
|
||||
@@ -1,11 +1,11 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class GeneralAppTests {
|
||||
private readonly EditorViewModel editor;
|
||||
private readonly StubFileSystem fileSystem;
|
||||
@@ -8,8 +8,8 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{B6A52732-E0F8-466D-8E29-664C797A21FA}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>HavenSoft.Gen3Hex.Tests</RootNamespace>
|
||||
<AssemblyName>Gen3Hex.Tests</AssemblyName>
|
||||
<RootNamespace>HavenSoft.HexManiac.Tests</RootNamespace>
|
||||
<AssemblyName>HexManiac.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
@@ -55,11 +55,12 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\artifacts\Gen3Hex.Tests\codegen\StubDataModel.cs">
|
||||
<Compile Include="..\..\artifacts\$(AssemblyName)\codegen\StubDataModel.cs">
|
||||
<Link>StubDataModel.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="ArrayRunTests.cs" />
|
||||
<Compile Include="ChangeHistoryTests.cs" />
|
||||
<Compile Include="AsciiRunTests.cs" />
|
||||
<Compile Include="FindTests.cs" />
|
||||
<Compile Include="GeneralAppTests.cs" />
|
||||
<Compile Include="..\..\artifacts\$(AssemblyName)\codegen\StubFileSystem.cs" />
|
||||
@@ -82,9 +83,9 @@
|
||||
<Analyzer Include="..\..\packages\xunit.analyzers.0.10.0\analyzers\dotnet\cs\xunit.analyzers.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Gen3Hex.Core\Gen3Hex.Core.csproj">
|
||||
<ProjectReference Include="..\HexManiac.Core\HexManiac.Core.csproj">
|
||||
<Project>{b7b9d932-4271-493d-aadd-6cf147c91373}</Project>
|
||||
<Name>Gen3Hex.Core</Name>
|
||||
<Name>HexManiac.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
@@ -102,7 +103,7 @@
|
||||
<PreBuildEvent>
|
||||
if not exist $(SolutionDir)artifacts\$(AssemblyName)\codegen mkdir $(SolutionDir)artifacts\$(AssemblyName)\codegen
|
||||
|
||||
$(SolutionDir)packages\HavenSoft.AutoImplement.1.1.1\AutoImplement $(SolutionDir)artifacts\Gen3Hex.Core\bin\$(ConfigurationName)\Gen3Hex.Core.dll ITabContent IFileSystem IViewPort IDataModel
|
||||
$(SolutionDir)packages\HavenSoft.AutoImplement.1.1.1\AutoImplement $(SolutionDir)artifacts\HexManiac.Core\bin\$(ConfigurationName)\HexManiac.Core.dll ITabContent IFileSystem IViewPort IDataModel
|
||||
move /Y StubTabContent.cs $(SolutionDir)artifacts\$(AssemblyName)\codegen
|
||||
move /Y StubFileSystem.cs $(SolutionDir)artifacts\$(AssemblyName)\codegen
|
||||
move /Y StubViewPort.cs $(SolutionDir)artifacts\$(AssemblyName)\codegen
|
||||
@@ -1,11 +1,11 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Input;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class NavigationTests {
|
||||
[Fact]
|
||||
public void AddressesAreCorrect() {
|
||||
@@ -1,14 +1,14 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class PointerModelTests {
|
||||
[Fact]
|
||||
public void PointerModelFindsNoPointersInRandomData() {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class StringModelTests {
|
||||
[Fact]
|
||||
public void CanRecognizeString() {
|
||||
@@ -1,15 +1,15 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.Models.Runs;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.Tools;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Tools;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class ToolTests {
|
||||
[Fact]
|
||||
public void ViewPortHasTools() {
|
||||
@@ -1,8 +1,8 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class ViewPortCursorTests {
|
||||
[Fact]
|
||||
public void CursorCanMoveAllFourDirections() {
|
||||
@@ -1,12 +1,12 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class ViewPortEditTests {
|
||||
[Fact]
|
||||
public void CanEditData() {
|
||||
@@ -1,13 +1,13 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class ViewPortSaveTests {
|
||||
|
||||
private readonly StubFileSystem fileSystem;
|
||||
@@ -1,11 +1,11 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
[assembly: System.Reflection.AssemblyTitle("HexTests")]
|
||||
|
||||
namespace HavenSoft.Gen3Hex.Tests {
|
||||
namespace HavenSoft.HexManiac.Tests {
|
||||
public class ViewPortTests {
|
||||
[Fact]
|
||||
public void ViewPortNotifiesOnSizeChange() {
|
||||
@@ -1,8 +1,8 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.Gen3Hex.WPF.Implementations;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.WPF.Implementations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
@@ -14,10 +14,10 @@ using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using ModelPoint = HavenSoft.Gen3Hex.Core.Models.Point;
|
||||
using ModelPoint = HavenSoft.HexManiac.Core.Models.Point;
|
||||
using ScreenPoint = System.Windows.Point;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Controls {
|
||||
namespace HavenSoft.HexManiac.WPF.Controls {
|
||||
|
||||
public class HexContent : FrameworkElement {
|
||||
public const double CellWidth = 30, CellHeight = 20;
|
||||
@@ -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 {
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Controls {
|
||||
namespace HavenSoft.HexManiac.WPF.Controls {
|
||||
public class IntegerToBooleanViaMatchConverter : IValueConverter {
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
var a = value as int?;
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Controls {
|
||||
namespace HavenSoft.HexManiac.WPF.Controls {
|
||||
public class IntegerToHexConverter : IValueConverter {
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
if (value is int number) return number.ToString("X6");
|
||||
51
src/HexManiac.WPF/Controls/StartScreen.xaml
Normal file
51
src/HexManiac.WPF/Controls/StartScreen.xaml
Normal file
@@ -0,0 +1,51 @@
|
||||
<Grid x:Class="HavenSoft.HexManiac.WPF.Controls.StartScreen"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:solarized="clr-namespace:Solarized"
|
||||
xmlns:hsg3hwr="clr-namespace:HavenSoft.HexManiac.WPF.Resources"
|
||||
mc:Ignorable="d" Background="{DynamicResource Background}"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="400"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Foreground="{DynamicResource Primary}" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
Drag-n-Drop to open a file.
|
||||
</TextBlock>
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center" TextBlock.Foreground="{DynamicResource Primary}" >
|
||||
<Border Margin="5" Padding="5" Background="{DynamicResource Background}" BorderBrush="{DynamicResource Secondary}" CornerRadius="5,5,5,5" BorderThickness="1" Cursor="Hand" MouseLeftButtonDown="PointerHelp">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="30"/>
|
||||
<RowDefinition Height="30"/>
|
||||
<RowDefinition Height="30"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="1" FontFamily="Consolas" Foreground="{solarized:Theme Blue}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="35,0"><pointer></TextBlock>
|
||||
<TextBlock Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="35,0"><Run FontFamily="Consolas" Foreground="{solarized:Theme Blue}">^</Run>Anchor</TextBlock>
|
||||
<Path Data="M0,0 A230,150 0 0 1 230,0 L228,-10 M230,0 L224,7.5" HorizontalAlignment="Center" VerticalAlignment="Bottom" StrokeThickness="1" Stroke="{solarized:Theme Blue}">
|
||||
<Path.RenderTransform>
|
||||
<TranslateTransform X="0" Y="10"/>
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
<Border HorizontalAlignment="Center" Background="{DynamicResource Background}" Padding="5,0">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path Data="{hsg3hwr:Icon CtrlKey}" Fill="{DynamicResource Secondary}" Stretch="Uniform"/>
|
||||
<Path Data="{hsg3hwr:Icon ThinPlus}" Fill="{DynamicResource Secondary}" Stretch="Uniform" Margin="2" Width="10"/>
|
||||
<Path Height="30" Data="{hsg3hwr:Icon LeftMouseButton}" Fill="{DynamicResource Secondary}" Stretch="Uniform"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Path Grid.Row="2" Data="M230,0 A230,150 0 0 1 0,0 L2,10 M0,0 L7.5,-6" HorizontalAlignment="Center" VerticalAlignment="Top" StrokeThickness="1" Stroke="{solarized:Theme Blue}">
|
||||
<Path.RenderTransform>
|
||||
<TranslateTransform X="0" Y="-1"/>
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
<Border Grid.Row="2" HorizontalAlignment="Center" Background="{DynamicResource Background}" Padding="5,0">
|
||||
<Path Height="30" Data="{hsg3hwr:Icon RightMouseButton}" Fill="{DynamicResource Secondary}" Stretch="Uniform"/>
|
||||
</Border>
|
||||
<TextBlock Foreground="{DynamicResource Secondary}" FontStyle="Italic" TextDecorations="Underline" Grid.Row="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Text="click for more info" Margin="5"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
13
src/HexManiac.WPF/Controls/StartScreen.xaml.cs
Normal file
13
src/HexManiac.WPF/Controls/StartScreen.xaml.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.HexManiac.WPF.Controls {
|
||||
public partial class StartScreen {
|
||||
public StartScreen() => InitializeComponent();
|
||||
|
||||
private void PointerHelp(object sender, MouseButtonEventArgs e) {
|
||||
Process.Start(new ProcessStartInfo("https://github.com/haven1433/HexManiacAdvance/wiki/Pointers-and-Anchors"));
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{386DC8E2-BABC-475C-94B6-37B3986F5F4C}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>HavenSoft.Gen3Hex.WPF</RootNamespace>
|
||||
<AssemblyName>Gen3Hex</AssemblyName>
|
||||
<RootNamespace>HavenSoft.HexManiac.WPF</RootNamespace>
|
||||
<AssemblyName>HexManiacAdvance</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
@@ -32,7 +32,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Resources\Snorlax.ico</ApplicationIcon>
|
||||
<ApplicationIcon>Resources\AppIcon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
@@ -54,6 +54,10 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="Controls\StartScreen.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Windows\AboutWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -68,6 +72,9 @@
|
||||
</Page>
|
||||
<Compile Include="Controls\IntegerToBooleanViaMatchConverter.cs" />
|
||||
<Compile Include="Controls\IntegerToHexConverter.cs" />
|
||||
<Compile Include="Controls\StartScreen.xaml.cs">
|
||||
<DependentUpon>StartScreen.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Windows\AboutWindow.xaml.cs">
|
||||
<DependentUpon>AboutWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -95,14 +102,16 @@
|
||||
<None Include="Windows\App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Gen3Hex.Core\Gen3Hex.Core.csproj">
|
||||
<ProjectReference Include="..\HexManiac.Core\HexManiac.Core.csproj">
|
||||
<Project>{b7b9d932-4271-493d-aadd-6cf147c91373}</Project>
|
||||
<Name>Gen3Hex.Core</Name>
|
||||
<Name>HexManiac.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Snorlax.ico" />
|
||||
<Resource Include="Resources\snorlax.png" />
|
||||
<Resource Include="Resources\AppIcon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\AppImage.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,12 +1,12 @@
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.Gen3Hex.WPF.Controls;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.WPF.Controls;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Implementations {
|
||||
namespace HavenSoft.HexManiac.WPF.Implementations {
|
||||
public class FormatDrawer : IDataFormatVisitor {
|
||||
public static int FontSize = 16;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace HavenSoft.Gen3Hex.WPF.Implementations {
|
||||
|
||||
public bool MouseIsOverCurrentFormat { get; set; }
|
||||
|
||||
public HavenSoft.Gen3Hex.Core.Models.Point Position { get; set; }
|
||||
public HavenSoft.HexManiac.Core.Models.Point Position { get; set; }
|
||||
|
||||
public FormatDrawer(DrawingContext drawingContext, int width, int height) => (context, modelWidth, modelHeight) = (drawingContext, width, height);
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace HavenSoft.Gen3Hex.WPF.Implementations {
|
||||
brush,
|
||||
1.0);
|
||||
|
||||
if (dataFormat.Position < Position.X || Position.X - dataFormat.Position > modelWidth - 4) {
|
||||
if (dataFormat.Position > Position.X || Position.X - dataFormat.Position > modelWidth - 4) {
|
||||
context.PushClip(rectangleGeometry);
|
||||
context.DrawText(text, new Point(CellTextOffset.X + xOffset, CellTextOffset.Y));
|
||||
context.Pop();
|
||||
@@ -131,6 +131,20 @@ namespace HavenSoft.Gen3Hex.WPF.Implementations {
|
||||
context.DrawText(text, CellTextOffset);
|
||||
}
|
||||
|
||||
public void Visit(Ascii ascii, byte data) {
|
||||
var typeface = new Typeface("Consolas");
|
||||
var text = new FormattedText(
|
||||
ascii.ThisCharacter.ToString(),
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
FontSize,
|
||||
Solarized.Brushes.Violet,
|
||||
1.0);
|
||||
|
||||
context.DrawText(text, CellTextOffset);
|
||||
}
|
||||
|
||||
private void Underline(Brush brush, bool isStart, bool isEnd) {
|
||||
int startPoint = isStart ? 5 : 0;
|
||||
int endPoint = (int)HexContent.CellWidth - (isEnd ? 5 : 0);
|
||||
@@ -1,4 +1,4 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -7,7 +7,7 @@ using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Implementations {
|
||||
namespace HavenSoft.HexManiac.WPF.Implementations {
|
||||
public class WindowsFileSystem : IFileSystem {
|
||||
private readonly Dictionary<string, List<FileSystemWatcher>> watchers = new Dictionary<string, List<FileSystemWatcher>>();
|
||||
private readonly Dictionary<string, List<Action<IFileSystem>>> listeners = new Dictionary<string, List<Action<IFileSystem>>>();
|
||||
BIN
src/HexManiac.WPF/Resources/AppIcon.ico
Normal file
BIN
src/HexManiac.WPF/Resources/AppIcon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 766 B |
BIN
src/HexManiac.WPF/Resources/AppImage.png
Normal file
BIN
src/HexManiac.WPF/Resources/AppImage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -4,14 +4,14 @@
|
||||
This ItemsControl is meant to be used like a resource.
|
||||
Instead, access these icons using IconExtensions.
|
||||
-->
|
||||
<ItemsControl x:Class="HavenSoft.Gen3Hex.WPF.Resources.Icons"
|
||||
<ItemsControl x:Class="HavenSoft.HexManiac.WPF.Resources.Icons"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:hsv="clr-namespace:HavenSoft.Gen3Hex.WPF.Resources"
|
||||
xmlns:hsv="clr-namespace:HavenSoft.HexManiac.WPF.Resources"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300" d:DesignWidth="300">
|
||||
d:DesignHeight="360" d:DesignWidth="360">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel/>
|
||||
@@ -163,5 +163,68 @@
|
||||
</GeometryGroup>
|
||||
<PathGeometry x:Name="SizeArrow" Figures="M -6,-6 L 6,-6 6,6 -6,6 Z M 4,4 L -4,4 4,-4 Z M -4,-4 l 5,0 -5,5 Z"/>
|
||||
<PathGeometry x:Name="SizeArrow2" Figures="M 4,4 L -4,4 4,-4 Z M -4,-4 l 5,0 -5,5 Z"/>
|
||||
<CombinedGeometry x:Name="LeftMouseButton" GeometryCombineMode="Exclude">
|
||||
<CombinedGeometry.Geometry1>
|
||||
<GeometryGroup FillRule="Nonzero">
|
||||
<EllipseGeometry RadiusX="10" RadiusY="10"/>
|
||||
<EllipseGeometry Center="0,10" RadiusX="10" RadiusY="10"/>
|
||||
<RectangleGeometry Rect="-10,0,20,10"/>
|
||||
</GeometryGroup>
|
||||
</CombinedGeometry.Geometry1>
|
||||
<CombinedGeometry.Geometry2>
|
||||
<GeometryGroup FillRule="Nonzero">
|
||||
<CombinedGeometry GeometryCombineMode="Exclude">
|
||||
<CombinedGeometry.Geometry1>
|
||||
<EllipseGeometry RadiusX="8" RadiusY="8"/>
|
||||
</CombinedGeometry.Geometry1>
|
||||
<CombinedGeometry.Geometry2>
|
||||
<GeometryGroup FillRule="Nonzero">
|
||||
<RectangleGeometry Rect="0,-10,10,20"/>
|
||||
<RectangleGeometry Rect="-10,0,10,10"/>
|
||||
</GeometryGroup>
|
||||
</CombinedGeometry.Geometry2>
|
||||
</CombinedGeometry>
|
||||
<RectangleGeometry Rect="-8,0,8,4"/>
|
||||
</GeometryGroup>
|
||||
</CombinedGeometry.Geometry2>
|
||||
</CombinedGeometry>
|
||||
<CombinedGeometry x:Name="RightMouseButton" GeometryCombineMode="Exclude">
|
||||
<CombinedGeometry.Geometry1>
|
||||
<GeometryGroup FillRule="Nonzero">
|
||||
<EllipseGeometry RadiusX="10" RadiusY="10"/>
|
||||
<EllipseGeometry Center="0,10" RadiusX="10" RadiusY="10"/>
|
||||
<RectangleGeometry Rect="-10,0,20,10"/>
|
||||
</GeometryGroup>
|
||||
</CombinedGeometry.Geometry1>
|
||||
<CombinedGeometry.Geometry2>
|
||||
<GeometryGroup FillRule="Nonzero">
|
||||
<CombinedGeometry GeometryCombineMode="Exclude">
|
||||
<CombinedGeometry.Geometry1>
|
||||
<EllipseGeometry RadiusX="8" RadiusY="8"/>
|
||||
</CombinedGeometry.Geometry1>
|
||||
<CombinedGeometry.Geometry2>
|
||||
<GeometryGroup FillRule="Nonzero">
|
||||
<RectangleGeometry Rect="-10,-10,10,20"/>
|
||||
<RectangleGeometry Rect="0,0,10,10"/>
|
||||
</GeometryGroup>
|
||||
</CombinedGeometry.Geometry2>
|
||||
</CombinedGeometry>
|
||||
<RectangleGeometry Rect="0,0,8,4"/>
|
||||
</GeometryGroup>
|
||||
</CombinedGeometry.Geometry2>
|
||||
</CombinedGeometry>
|
||||
<CombinedGeometry x:Name="CtrlKey" GeometryCombineMode="Exclude" Geometry2="{hsv:TextGeometry Ctrl,0,0,12}">
|
||||
<CombinedGeometry.Geometry1>
|
||||
<RectangleGeometry Rect="-1,2,20,11" RadiusX="2" RadiusY="2"/>
|
||||
</CombinedGeometry.Geometry1>
|
||||
</CombinedGeometry>
|
||||
<CombinedGeometry x:Name="ThinPlus" GeometryCombineMode="Union">
|
||||
<CombinedGeometry.Geometry1>
|
||||
<RectangleGeometry Rect="-5,0,12,2"/>
|
||||
</CombinedGeometry.Geometry1>
|
||||
<CombinedGeometry.Geometry2>
|
||||
<RectangleGeometry Rect="0,-5,2,12"/>
|
||||
</CombinedGeometry.Geometry2>
|
||||
</CombinedGeometry>
|
||||
</ItemsControl.Items>
|
||||
</ItemsControl>
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace HavenSoft.Gen3Hex.WPF.Resources {
|
||||
namespace HavenSoft.HexManiac.WPF.Resources {
|
||||
partial class Icons {
|
||||
public Icons() => InitializeComponent();
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Resources {
|
||||
namespace HavenSoft.HexManiac.WPF.Resources {
|
||||
/// <example>
|
||||
/// {hs:RotateTransform 60, 0, 0}
|
||||
/// </example>
|
||||
public class RotateTransformExtension : MarkupExtension {
|
||||
readonly double Angle;
|
||||
readonly double CenterX;
|
||||
readonly double CenterY;
|
||||
public double Angle { get; }
|
||||
public double CenterX { get; }
|
||||
public double CenterY { get; }
|
||||
|
||||
public RotateTransformExtension(double angle, double centerX, double centerY) {
|
||||
Angle = angle;
|
||||
@@ -27,7 +28,7 @@ namespace HavenSoft.Gen3Hex.WPF.Resources {
|
||||
/// {hs:Geometry 'M0,0 L0,1 1,1 1,0 Z'}
|
||||
/// </example>
|
||||
public class GeometryExtension : MarkupExtension {
|
||||
readonly string Figures;
|
||||
public string Figures { get; }
|
||||
|
||||
public GeometryExtension(string figures) { Figures = figures; }
|
||||
|
||||
@@ -36,6 +37,18 @@ namespace HavenSoft.Gen3Hex.WPF.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
public class TextGeometryExtension : MarkupExtension {
|
||||
public string Text { get; set; }
|
||||
public Point Location { get; set; }
|
||||
public int Size { get; set; }
|
||||
public TextGeometryExtension() { }
|
||||
public TextGeometryExtension(string text, int x, int y, int size) => (Text, Location, Size) = (text, new Point(x, y), size);
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) {
|
||||
var formattedText = new FormattedText(Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Calibri"), Size, Brushes.Black, 1);
|
||||
return formattedText.BuildGeometry(Location);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Icons are taken from Icons.xaml
|
||||
/// Requires that there is an Icons instance stored at "Icons" in the app resources.
|
||||
@@ -45,7 +58,7 @@ namespace HavenSoft.Gen3Hex.WPF.Resources {
|
||||
/// {hs:Icons Save}
|
||||
/// </example>
|
||||
public class IconExtension : MarkupExtension {
|
||||
readonly string Name;
|
||||
public string Name { get; }
|
||||
|
||||
public IconExtension(string name) { Name = name; }
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
<Window x:Class="HavenSoft.Gen3Hex.WPF.Windows.AboutWindow"
|
||||
<Window x:Class="HavenSoft.HexManiac.WPF.Windows.AboutWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:solarized="clr-namespace:Solarized"
|
||||
Background="{DynamicResource Background}"
|
||||
WindowStyle="ToolWindow"
|
||||
Title="About Gen3Hex" Height="300" Width="400">
|
||||
Title="About Hex Maniac Advance" Height="300" Width="400">
|
||||
<DockPanel Margin="15">
|
||||
<TextBlock DockPanel.Dock="Bottom" FontStyle="Italic" TextWrapping="Wrap">
|
||||
Gen3Hex is a non-profit open-source fan-made tool.
|
||||
Hex Maniac Advance is a non-profit open-source fan-made tool.
|
||||
Only use it with legally purchased software.
|
||||
Pokemon is the property of Nintendo and GameFreak.
|
||||
Please support the official release.
|
||||
</TextBlock>
|
||||
<TextBlock DockPanel.Dock="Top" VerticalAlignment="Center" FontWeight="Bold" Text="Gen3Hex" FontSize="20"/>
|
||||
<Image Source="..\Resources\Snorlax.png" DockPanel.Dock="Left" RenderOptions.BitmapScalingMode="Fant"/>
|
||||
<TextBlock DockPanel.Dock="Top" VerticalAlignment="Center" FontWeight="Bold" Text="Hex Maniac Advance" FontSize="20"/>
|
||||
<Image Source="..\Resources\AppImage.png" DockPanel.Dock="Left" RenderOptions.BitmapScalingMode="Fant" Width="200"/>
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock Name="Version"/>
|
||||
<TextBlock TextWrapping="Wrap">This is a prerelease debug version: please do not distribute!</TextBlock>
|
||||
<TextBlock>
|
||||
<Hyperlink Foreground="{solarized:Theme Blue}" NavigateUri="https://github.com/haven1433/gen3hex/blob/master/LICENSE" RequestNavigate="Navigate">MIT License</Hyperlink>
|
||||
<Hyperlink Foreground="{solarized:Theme Blue}" NavigateUri="https://github.com/haven1433/HexManiacAdvance/blob/master/LICENSE" RequestNavigate="Navigate">MIT License</Hyperlink>
|
||||
</TextBlock>
|
||||
<TextBlock>
|
||||
<Hyperlink Foreground="{solarized:Theme Blue}" NavigateUri="https://ethanschoonover.com/solarized" RequestNavigate="Navigate">Solarized</Hyperlink>
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Reflection;
|
||||
using System.Windows.Navigation;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Windows {
|
||||
namespace HavenSoft.HexManiac.WPF.Windows {
|
||||
partial class AboutWindow {
|
||||
public AboutWindow() {
|
||||
InitializeComponent();
|
||||
@@ -1,7 +1,7 @@
|
||||
<Application x:Class="HavenSoft.Gen3Hex.WPF.Windows.App"
|
||||
<Application x:Class="HavenSoft.HexManiac.WPF.Windows.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:hsv="clr-namespace:HavenSoft.Gen3Hex.WPF.Resources"
|
||||
xmlns:hsv="clr-namespace:HavenSoft.HexManiac.WPF.Resources"
|
||||
xmlns:solarized="clr-namespace:Solarized">
|
||||
<Application.Resources>
|
||||
<!-- Icons accessible using IconExtension -->
|
||||
@@ -1,13 +1,13 @@
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.WPF.Implementations;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.WPF.Implementations;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
|
||||
[assembly: AssemblyTitle("Gen3Hex")]
|
||||
[assembly: AssemblyTitle("HexManiacAdvance")]
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Windows {
|
||||
namespace HavenSoft.HexManiac.WPF.Windows {
|
||||
partial class App {
|
||||
protected override void OnStartup(StartupEventArgs e) {
|
||||
base.OnStartup(e);
|
||||
@@ -1,14 +1,14 @@
|
||||
<Window x:Class="HavenSoft.Gen3Hex.WPF.Windows.MainWindow"
|
||||
<Window x:Class="HavenSoft.HexManiac.WPF.Windows.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:hsg3ww="clr-namespace:HavenSoft.Gen3Hex.WPF.Windows"
|
||||
xmlns:hsg3hv="clr-namespace:HavenSoft.Gen3Hex.WPF.Controls"
|
||||
xmlns:hsv="clr-namespace:HavenSoft.Gen3Hex.WPF.Resources"
|
||||
xmlns:hsg3ww="clr-namespace:HavenSoft.HexManiac.WPF.Windows"
|
||||
xmlns:hsg3hv="clr-namespace:HavenSoft.HexManiac.WPF.Controls"
|
||||
xmlns:hsv="clr-namespace:HavenSoft.HexManiac.WPF.Resources"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:solarized="clr-namespace:Solarized"
|
||||
Icon="..\Resources\Snorlax.ico"
|
||||
Icon="..\Resources\AppIcon.ico"
|
||||
PreviewMouseDown="RunDeferredActions"
|
||||
Title="Gen3Hex" Height="450" Width="870" AllowDrop="True" Background="{DynamicResource Background}">
|
||||
Title="Hex Maniac Advance" Height="450" Width="870" AllowDrop="True" Background="{DynamicResource Background}">
|
||||
<Window.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||
<hsg3hv:IntegerToBooleanViaMatchConverter x:Key="IndexMatch"/>
|
||||
@@ -219,147 +219,159 @@
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</DockPanel>
|
||||
<TabControl Name="Tabs" ItemsSource="{Binding}" SelectedIndex="{Binding SelectedIndex}">
|
||||
<TabControl.InputBindings>
|
||||
<KeyBinding Key="Esc" Command="{Binding HideSearchControls}"/>
|
||||
</TabControl.InputBindings>
|
||||
<TabControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Name="TabTextBlock" Background="Transparent" Text="{Binding Name}" Foreground="{DynamicResource Primary}" MouseDown="TabMouseDown" MouseMove="TabMouseMove" MouseUp="TabMouseUp">
|
||||
<TextBlock.InputBindings>
|
||||
<MouseBinding MouseAction="MiddleClick" Command="{Binding Close}" CommandParameter="{DynamicResource FileSystem}"/>
|
||||
</TextBlock.InputBindings>
|
||||
</TextBlock>
|
||||
<Button Command="{Binding Close}" Width="15" Margin="5,0,0,0" VerticalAlignment="Stretch" Background="{DynamicResource Background}" BorderBrush="{DynamicResource Background}">
|
||||
<Path Data="{hsv:Icon Exit}" Fill="{DynamicResource Secondary}" Stretch="Uniform"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</TabControl.ItemTemplate>
|
||||
<TabControl.ContentTemplate>
|
||||
<DataTemplate>
|
||||
<DockPanel>
|
||||
<Border DockPanel.Dock="Top" Height="19" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Backlight}">
|
||||
<TextBox Text="{Binding AnchorText, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding AnchorTextVisible, Converter={StaticResource BoolToVisibility}}" Margin="60,0,25,0"/>
|
||||
</Border>
|
||||
<!-- Headers -->
|
||||
<ItemsControl DockPanel.Dock="Left" Width="60" ItemsSource="{Binding Headers}" Background="{DynamicResource Backlight}" MouseDown="HeaderMouseDown">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Foreground="{DynamicResource Secondary}" Text="{Binding}" FontFamily="Consolas" HorizontalAlignment="Right" Height="{x:Static hsg3hv:HexContent.CellHeight}" Padding="4"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Line Width="1" DockPanel.Dock="Left" Stroke="{DynamicResource Background}"/>
|
||||
<StackPanel DockPanel.Dock="Right" Visibility="{Binding HasTools, Converter={StaticResource BoolToVisibility}}">
|
||||
<Button Content="Text" Command="{Binding Tools.StringToolCommand}" Margin="0,2">
|
||||
<Button.LayoutTransform>
|
||||
<RotateTransform Angle="90"/>
|
||||
</Button.LayoutTransform>
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Tools.SelectedIndex}" Value="0">
|
||||
<Setter Property="BorderBrush" Value="{solarized:Theme Blue}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<Button Content="Tool2" Command="{Binding Tools.Tool2Command}" Margin="0,2">
|
||||
<Button.LayoutTransform>
|
||||
<RotateTransform Angle="90"/>
|
||||
</Button.LayoutTransform>
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Tools.SelectedIndex}" Value="1">
|
||||
<Setter Property="BorderBrush" Value="{solarized:Theme Blue}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<Button Content="Tool3" Command="{Binding Tools.Tool3Command}" Margin="0,2">
|
||||
<Button.LayoutTransform>
|
||||
<RotateTransform Angle="90"/>
|
||||
</Button.LayoutTransform>
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Tools.SelectedIndex}" Value="2">
|
||||
<Setter Property="BorderBrush" Value="{solarized:Theme Blue}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
<Grid>
|
||||
<hsg3hv:StartScreen/>
|
||||
<TabControl Name="Tabs" ItemsSource="{Binding}" SelectedIndex="{Binding SelectedIndex}">
|
||||
<TabControl.Style>
|
||||
<Style TargetType="TabControl" BasedOn="{StaticResource {x:Type TabControl}}">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="SelectedIndex" Value="-1">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TabControl.Style>
|
||||
<TabControl.InputBindings>
|
||||
<KeyBinding Key="Esc" Command="{Binding HideSearchControls}"/>
|
||||
</TabControl.InputBindings>
|
||||
<TabControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Name="TabTextBlock" Background="Transparent" Text="{Binding Name}" Foreground="{DynamicResource Primary}" MouseDown="TabMouseDown" MouseMove="TabMouseMove" MouseUp="TabMouseUp">
|
||||
<TextBlock.InputBindings>
|
||||
<MouseBinding MouseAction="MiddleClick" Command="{Binding Close}" CommandParameter="{DynamicResource FileSystem}"/>
|
||||
</TextBlock.InputBindings>
|
||||
</TextBlock>
|
||||
<Button Command="{Binding Close}" Width="15" Margin="5,0,0,0" VerticalAlignment="Stretch" Background="{DynamicResource Background}" BorderBrush="{DynamicResource Background}">
|
||||
<Path Data="{hsv:Icon Exit}" Fill="{DynamicResource Secondary}" Stretch="Uniform"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<!-- Tools -->
|
||||
<Grid DockPanel.Dock="Right" DataContext="{Binding Tools}">
|
||||
<Grid.Style>
|
||||
<Style TargetType="Grid">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedIndex}" Value="-1">
|
||||
</DataTemplate>
|
||||
</TabControl.ItemTemplate>
|
||||
<TabControl.ContentTemplate>
|
||||
<DataTemplate>
|
||||
<DockPanel>
|
||||
<Border DockPanel.Dock="Top" Height="19" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Backlight}">
|
||||
<TextBox Text="{Binding AnchorText, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding AnchorTextVisible, Converter={StaticResource BoolToVisibility}}" Margin="60,0,25,0"/>
|
||||
</Border>
|
||||
<!-- Headers -->
|
||||
<ItemsControl DockPanel.Dock="Left" Width="60" ItemsSource="{Binding Headers}" Background="{DynamicResource Backlight}" MouseDown="HeaderMouseDown">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Foreground="{DynamicResource Secondary}" Text="{Binding}" FontFamily="Consolas" HorizontalAlignment="Right" Height="{x:Static hsg3hv:HexContent.CellHeight}" Padding="4"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Line Width="1" DockPanel.Dock="Left" Stroke="{DynamicResource Background}"/>
|
||||
<StackPanel DockPanel.Dock="Right" Visibility="{Binding HasTools, Converter={StaticResource BoolToVisibility}}">
|
||||
<Button Content="Text" Command="{Binding Tools.StringToolCommand}" Margin="0,2">
|
||||
<Button.LayoutTransform>
|
||||
<RotateTransform Angle="90"/>
|
||||
</Button.LayoutTransform>
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Tools.SelectedIndex}" Value="0">
|
||||
<Setter Property="BorderBrush" Value="{solarized:Theme Blue}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<Button Content="Tool2" Command="{Binding Tools.Tool2Command}" Margin="0,2">
|
||||
<Button.LayoutTransform>
|
||||
<RotateTransform Angle="90"/>
|
||||
</Button.LayoutTransform>
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Tools.SelectedIndex}" Value="1">
|
||||
<Setter Property="BorderBrush" Value="{solarized:Theme Blue}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<Button Content="Tool3" Command="{Binding Tools.Tool3Command}" Margin="0,2">
|
||||
<Button.LayoutTransform>
|
||||
<RotateTransform Angle="90"/>
|
||||
</Button.LayoutTransform>
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Tools.SelectedIndex}" Value="2">
|
||||
<Setter Property="BorderBrush" Value="{solarized:Theme Blue}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<!-- Tools -->
|
||||
<Grid DockPanel.Dock="Right" DataContext="{Binding Tools}">
|
||||
<Grid.Style>
|
||||
<Style TargetType="Grid">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedIndex}" Value="-1">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Grid.Style>
|
||||
<DockPanel Name="StringToolPanel">
|
||||
<DockPanel.Style>
|
||||
<Style TargetType="DockPanel">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Grid.Style>
|
||||
<DockPanel Name="StringToolPanel">
|
||||
<DockPanel.Style>
|
||||
<Style TargetType="DockPanel">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedIndex}" Value="0">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DockPanel.Style>
|
||||
<TextBlock Text="Address:" Margin="5,15,0,0" DockPanel.Dock="Top"/>
|
||||
<TextBox Text="{Binding StringTool.Address, Converter={StaticResource Hex}}" Margin="5" DockPanel.Dock="Top"/>
|
||||
<TextBlock Text="Content:" Margin="5,30,0,0" DockPanel.Dock="Top"/>
|
||||
<TextBox Margin="5,5" AcceptsReturn="True" MinHeight="50" Width="255" TextWrapping="Wrap" FontFamily="Consolas" VerticalScrollBarVisibility="Auto"
|
||||
SelectionChanged="StringToolContentSelectionChanged"
|
||||
IsEnabled="{Binding StringTool.Enabled}"
|
||||
Text="{Binding StringTool.Content, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</DockPanel>
|
||||
<StackPanel Name="Tool2Panel">
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedIndex}" Value="1">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<TextBlock Text="Coming Soon!" Margin="5,15,0,0"/>
|
||||
</StackPanel>
|
||||
<StackPanel Name="Tool3Panel">
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedIndex}" Value="2">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<TextBlock Text="Coming Soon!" Margin="5,15,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ScrollBar DockPanel.Dock="Right"
|
||||
Minimum="{Binding MinimumScroll}" Maximum="{Binding MaximumScroll}" Value="{Binding ScrollValue}"
|
||||
SmallChange="1" LargeChange="{Binding Height}" />
|
||||
<hsg3hv:HexContent x:Name="HexContent" ViewPort="{Binding}" ShowGrid="{Binding DataContext.ShowMatrix, RelativeSource={RelativeSource AncestorType=hsg3ww:MainWindow}}" Margin=".5,.5,0,0"/>
|
||||
</DockPanel>
|
||||
</DataTemplate>
|
||||
</TabControl.ContentTemplate>
|
||||
</TabControl>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedIndex}" Value="0">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DockPanel.Style>
|
||||
<TextBlock Text="Address:" Margin="5,15,0,0" DockPanel.Dock="Top"/>
|
||||
<TextBox Text="{Binding StringTool.Address, Converter={StaticResource Hex}}" Margin="5" DockPanel.Dock="Top"/>
|
||||
<TextBlock Text="Content:" Margin="5,30,0,0" DockPanel.Dock="Top"/>
|
||||
<TextBox Margin="5,5" AcceptsReturn="True" MinHeight="50" Width="255" TextWrapping="Wrap" FontFamily="Consolas" VerticalScrollBarVisibility="Auto"
|
||||
SelectionChanged="StringToolContentSelectionChanged"
|
||||
IsEnabled="{Binding StringTool.Enabled}"
|
||||
Text="{Binding StringTool.Content, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</DockPanel>
|
||||
<StackPanel Name="Tool2Panel">
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedIndex}" Value="1">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<TextBlock Text="Coming Soon!" Margin="5,15,0,0"/>
|
||||
</StackPanel>
|
||||
<StackPanel Name="Tool3Panel">
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedIndex}" Value="2">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<TextBlock Text="Coming Soon!" Margin="5,15,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ScrollBar DockPanel.Dock="Right"
|
||||
Minimum="{Binding MinimumScroll}" Maximum="{Binding MaximumScroll}" Value="{Binding ScrollValue}"
|
||||
SmallChange="1" LargeChange="{Binding Height}" />
|
||||
<hsg3hv:HexContent x:Name="HexContent" ViewPort="{Binding}" ShowGrid="{Binding DataContext.ShowMatrix, RelativeSource={RelativeSource AncestorType=hsg3ww:MainWindow}}" Margin=".5,.5,0,0"/>
|
||||
</DockPanel>
|
||||
</DataTemplate>
|
||||
</TabControl.ContentTemplate>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -1,8 +1,8 @@
|
||||
using HavenSoft.Gen3Hex.Core;
|
||||
using HavenSoft.Gen3Hex.Core.Models;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels;
|
||||
using HavenSoft.Gen3Hex.Core.ViewModels.Tools;
|
||||
using HavenSoft.Gen3Hex.WPF.Controls;
|
||||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Tools;
|
||||
using HavenSoft.HexManiac.WPF.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
@@ -13,7 +13,7 @@ using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace HavenSoft.Gen3Hex.WPF.Windows {
|
||||
namespace HavenSoft.HexManiac.WPF.Windows {
|
||||
partial class MainWindow {
|
||||
private readonly List<Action> deferredActions = new List<Action>();
|
||||
|
||||
@@ -119,8 +119,8 @@ namespace HavenSoft.Gen3Hex.WPF.Windows {
|
||||
if (ViewModel.Count == 0) Close();
|
||||
}
|
||||
|
||||
private void WikiClick(object sender, EventArgs e) => System.Diagnostics.Process.Start("https://github.com/haven1433/gen3hex/wiki");
|
||||
private void ReportIssueClick(object sender, EventArgs e) => System.Diagnostics.Process.Start("https://github.com/haven1433/gen3hex/issues");
|
||||
private void WikiClick(object sender, EventArgs e) => System.Diagnostics.Process.Start("https://github.com/haven1433/HexManiacAdvance/wiki");
|
||||
private void ReportIssueClick(object sender, EventArgs e) => System.Diagnostics.Process.Start("https://github.com/haven1433/HexManiacAdvance/issues");
|
||||
private void AboutClick(object sender, EventArgs e) => new AboutWindow().ShowDialog();
|
||||
|
||||
private void EditBoxVisibilityChanged(object sender, DependencyPropertyChangedEventArgs e) {
|
||||
Reference in New Issue
Block a user