mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-10-02 13:16:35 -05:00
adding column headers
This commit is contained in:
@@ -156,6 +156,53 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
||||
}
|
||||
}
|
||||
|
||||
public class ColumnHeader {
|
||||
public string ColumnTitle { get; }
|
||||
public int ByteWidth { get; }
|
||||
public ColumnHeader(string title, int byteWidth = 1) => (ColumnTitle, ByteWidth) = (title, byteWidth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a horizontal row of labels.
|
||||
/// Each entry is meant to label a column.
|
||||
/// </summary>
|
||||
public class HeaderRow {
|
||||
public IReadOnlyList<ColumnHeader> ColumnHeaders { get; }
|
||||
|
||||
public HeaderRow(ArrayRun source, int byteStart, int length) {
|
||||
var headers = new List<ColumnHeader>();
|
||||
// we know which 'byte' to start at, but we want to know what 'index' to start at
|
||||
// basically, count off each element to figure out how big it is
|
||||
int currentByte = 0;
|
||||
int startIndex = 0;
|
||||
while (currentByte < byteStart) {
|
||||
currentByte += source.ElementContent[startIndex].Length;
|
||||
startIndex++;
|
||||
}
|
||||
currentByte = 0;
|
||||
for (int i = 0; currentByte < length; i++) {
|
||||
var segment = source.ElementContent[(startIndex + i) % source.ElementContent.Count];
|
||||
headers.Add(new ColumnHeader(segment.Name, segment.Length));
|
||||
currentByte += segment.Length;
|
||||
}
|
||||
ColumnHeaders = headers;
|
||||
}
|
||||
|
||||
public HeaderRow(int start, int length) {
|
||||
var hex = "0123456789ABCDEF";
|
||||
var headers = new ColumnHeader[length];
|
||||
for (int i = 0; i < length; i++) headers[i] = new ColumnHeader(hex[(start + i) % 0x10].ToString());
|
||||
ColumnHeaders = headers;
|
||||
}
|
||||
|
||||
public static IReadOnlyList<HeaderRow> GetDefaultColumnHeaders(int columnCount) {
|
||||
if (columnCount > 0x10 && columnCount % 0x10 != 0) return new List<HeaderRow>();
|
||||
if (columnCount < 0x10 && 0x10 % columnCount != 0) return new List<HeaderRow>();
|
||||
if (columnCount >= 0x10) return new[] { new HeaderRow(0, columnCount) };
|
||||
return Enumerable.Range(0, 0x10 / columnCount).Select(i => new HeaderRow(columnCount * i, columnCount)).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public class ArrayRun : BaseRun {
|
||||
public const char ExtendArray = '+';
|
||||
public const char ArrayStart = '[';
|
||||
@@ -386,6 +433,23 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
||||
return new ArrayRun(owner, FormatString, Start, ElementCount, ElementContent, PointerSources, pointerSourcesForInnerElements);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arrays might want custom column headers.
|
||||
/// If so, this method can get them.
|
||||
/// </summary>
|
||||
public IReadOnlyList<HeaderRow> GetColumnHeaders(int columnCount) {
|
||||
// check if it's a multiple of the array width
|
||||
if (columnCount >= ElementLength) {
|
||||
if (columnCount % ElementLength != 0) return null;
|
||||
return new[] { new HeaderRow(this, 0, columnCount) };
|
||||
}
|
||||
|
||||
// check if it's a divisor of the array width
|
||||
if (ElementLength % columnCount != 0) return null;
|
||||
var segments = ElementLength / columnCount;
|
||||
return Enumerable.Range(0, segments).Select(i => new HeaderRow(this, columnCount * i, columnCount)).ToList();
|
||||
}
|
||||
|
||||
public void AppendTo(IDataModel data, StringBuilder text) {
|
||||
for (int i = 0; i < ElementCount; i++) {
|
||||
var offset = Start + i * ElementLength;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Tools;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -16,6 +17,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
int ScrollValue { get; set; }
|
||||
int MaximumScroll { get; }
|
||||
ObservableCollection<string> Headers { get; }
|
||||
ObservableCollection<HeaderRow> ColumnHeaders { get; }
|
||||
int DataOffset { get; }
|
||||
ICommand Scroll { get; } // parameter: Direction to scroll
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Tools;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -78,6 +79,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
|
||||
public bool AnchorTextVisible => false;
|
||||
|
||||
public ObservableCollection<HeaderRow> ColumnHeaders { get; }
|
||||
|
||||
#pragma warning disable 0067 // it's ok if events are never used
|
||||
public event EventHandler<string> OnError;
|
||||
public event EventHandler<string> OnMessage;
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
public int MaximumScroll => scroll.MaximumScroll;
|
||||
|
||||
public ObservableCollection<string> Headers => scroll.Headers;
|
||||
public ObservableCollection<HeaderRow> ColumnHeaders { get; }
|
||||
public int DataOffset => scroll.DataIndex;
|
||||
public ICommand Scroll => scroll.Scroll;
|
||||
|
||||
@@ -290,6 +291,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
|
||||
Model = model;
|
||||
FileName = fileName;
|
||||
ColumnHeaders = new ObservableCollection<HeaderRow>();
|
||||
|
||||
scroll = new ScrollRegion(model.TryGetUsefulHeader) { DataLength = Model.Count };
|
||||
scroll.PropertyChanged += ScrollPropertyChanged;
|
||||
@@ -1225,9 +1227,25 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
||||
}
|
||||
}
|
||||
|
||||
if (ColumnHeaders.Count == 0 || ColumnHeaders[0].ColumnHeaders.Count != Width) UpdateColumnHeaders();
|
||||
|
||||
NotifyCollectionChanged(ResetArgs);
|
||||
}
|
||||
|
||||
private void UpdateColumnHeaders() {
|
||||
var index = scroll.ViewPointToDataIndex(new Point(0, 0));
|
||||
var run = Model.GetNextRun(index) as ArrayRun;
|
||||
if (run != null && run.Start > index) run = null; // only use the run if it starts _before_ the screen
|
||||
var headers = run?.GetColumnHeaders(Width) ?? HeaderRow.GetDefaultColumnHeaders(Width);
|
||||
|
||||
for (int i = 0; i < headers.Count; i++) {
|
||||
if (i < ColumnHeaders.Count) ColumnHeaders[i] = headers[i];
|
||||
else ColumnHeaders.Add(headers[i]);
|
||||
}
|
||||
|
||||
while (ColumnHeaders.Count > headers.Count) ColumnHeaders.RemoveAt(ColumnHeaders.Count - 1);
|
||||
}
|
||||
|
||||
private IDataFormat WrapFormat(IFormattedRun run, IDataFormat format, int dataIndex) {
|
||||
if (run.PointerSources != null && run.Start == dataIndex) {
|
||||
var name = Model.GetAnchorFromAddress(-1, run.Start);
|
||||
|
||||
16
src/HexManiac.WPF/Controls/MultiplyConverter.cs
Normal file
16
src/HexManiac.WPF/Controls/MultiplyConverter.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace HavenSoft.HexManiac.WPF.Controls {
|
||||
public class MultiplyConverter : IValueConverter {
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
if (value is int number && parameter is double param) return number * param;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@
|
||||
</Page>
|
||||
<Compile Include="Controls\IntegerToBooleanViaMatchConverter.cs" />
|
||||
<Compile Include="Controls\IntegerToHexConverter.cs" />
|
||||
<Compile Include="Controls\MultiplyConverter.cs" />
|
||||
<Compile Include="Controls\StartScreen.xaml.cs">
|
||||
<DependentUpon>StartScreen.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||
<hsg3hv:IntegerToBooleanViaMatchConverter x:Key="IndexMatch"/>
|
||||
<hsg3hv:IntegerToHexConverter x:Key="Hex"/>
|
||||
<hsg3hv:MultiplyConverter x:Key="Mult"/>
|
||||
</Window.Resources>
|
||||
<Window.InputBindings>
|
||||
<KeyBinding Key="N" Modifiers="Ctrl" Command="{Binding New}" />
|
||||
@@ -257,7 +258,7 @@
|
||||
<!-- Anchor Editor -->
|
||||
<Border DockPanel.Dock="Top" Height="19" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Backlight}">
|
||||
<DockPanel Visibility="{Binding AnchorTextVisible, Converter={StaticResource BoolToVisibility}}" >
|
||||
<TextBlock Width="60" Text="Anchor: " TextAlignment="Right" ToolTipService.ShowDuration="15000">
|
||||
<TextBlock Width="70" Text="Anchor: " TextAlignment="Right" ToolTipService.ShowDuration="15000">
|
||||
<TextBlock.ToolTip>
|
||||
<ToolTip Background="{DynamicResource Backlight}" BorderBrush="{solarized:Theme Blue}" BorderThickness="1">
|
||||
<TextBlock TextAlignment="Left">
|
||||
@@ -277,7 +278,38 @@
|
||||
<TextBox Text="{Binding AnchorText, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,25,0"/>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<!-- Headers -->
|
||||
<!-- Column Headers -->
|
||||
<DockPanel DockPanel.Dock="Top">
|
||||
<TextBlock Width="70" Text="{Binding ArrayName}" DockPanel.Dock="Left"/>
|
||||
<ItemsControl ItemsSource="{Binding ColumnHeaders}" Background="{DynamicResource Backlight}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ItemsControl ItemsSource="{Binding ColumnHeaders}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Foreground="{DynamicResource Secondary}" Text="{Binding ColumnTitle}" FontFamily="Consolas" HorizontalAlignment="Left" Width="{Binding ByteWidth, Converter={StaticResource Mult}, ConverterParameter={x:Static hsg3hv:HexContent.CellWidth}}">
|
||||
<TextBlock.ToolTip>
|
||||
<ToolTip Background="{DynamicResource Backlight}" BorderBrush="{solarized:Theme Blue}" BorderThickness="1">
|
||||
<TextBlock TextAlignment="Left" Text="{Binding ColumnTitle}"/>
|
||||
</ToolTip>
|
||||
</TextBlock.ToolTip>
|
||||
<TextBlock.RenderTransform>
|
||||
<TranslateTransform X="5"/>
|
||||
</TextBlock.RenderTransform>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</DockPanel>
|
||||
<!-- Row Headers -->
|
||||
<ItemsControl DockPanel.Dock="Left" Width="70" ItemsSource="{Binding Headers}" Background="{DynamicResource Backlight}" MouseDown="HeaderMouseDown">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
||||
Reference in New Issue
Block a user