creating HexContent and its ViewModel, ViewPort. I expect that HexContent will represent an area of the screen filled with hex data. There will probably be a wrapper panel that adds the scrollbar to the right and addresses to the left. ViewPort can act as the ViewModel for that entire panel. Added a failing test so I remember to go back and make the ViewModel notify when it's Width/Height gets changed.

This commit is contained in:
Benjamin Popp
2018-09-11 22:20:37 -05:00
parent c541158043
commit e9380a5b79
10 changed files with 136 additions and 21 deletions

View File

@@ -47,19 +47,22 @@
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<ApplicationDefinition Include="View\App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Compile Include="ViewModel\HexElement.cs" />
<Compile Include="ViewModel\ViewPort.cs" />
<Page Include="View\MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<Compile Include="View\App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<Compile Include="View\HexContent.cs" />
<Compile Include="View\MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>

View File

@@ -1,11 +0,0 @@
<Window x:Class="HavenSoft.Gen3Hex.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Gen3Hex" Height="450" Width="800">
<Grid>
</Grid>
</Window>

View File

@@ -1,7 +1,7 @@
<Application x:Class="HavenSoft.Gen3Hex.App"
<Application x:Class="HavenSoft.Gen3Hex.View.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
StartupUri="View/MainWindow.xaml">
<Application.Resources>
</Application.Resources>

View File

@@ -2,7 +2,7 @@
[assembly: AssemblyTitle("Gen3Hex")]
namespace HavenSoft.Gen3Hex {
namespace HavenSoft.Gen3Hex.View {
public partial class App {
}
}

View File

@@ -0,0 +1,82 @@
using HavenSoft.Gen3Hex.ViewModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Media;
namespace HavenSoft.Gen3Hex.View {
public class HexContent : FrameworkElement {
public const int
CellWidth = 30,
CellHeight = 20;
public const string Hex = "0123456789ABCDEF";
private readonly List<FormattedText> byteVisualCache = new List<FormattedText>();
private ViewPort ViewModel => (ViewPort)DataContext;
public HexContent() {
DataContextChanged += OnDataContextChanged;
}
protected override void OnRender(DrawingContext drawingContext) {
base.OnRender(drawingContext);
var viewPort = ViewModel;
VerifyByteVisualCache();
for (int x = 0; x < viewPort.Width; x++) {
for (int y = 0; y < viewPort.Height; y++) {
var element = viewPort[x, y];
drawingContext.DrawText(byteVisualCache[element.Value], new Point(x * CellWidth, y * CellHeight));
}
}
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) {
base.OnRenderSizeChanged(sizeInfo);
ViewModel.Width = (int)sizeInfo.NewSize.Width / CellWidth;
ViewModel.Height = (int)sizeInfo.NewSize.Height / CellHeight;
}
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) {
if (e.OldValue is INotifyPropertyChanged oldContext) {
oldContext.PropertyChanged -= OnDataContextPropertyChanged;
}
if(e.NewValue is INotifyPropertyChanged newContext) {
newContext.PropertyChanged += OnDataContextPropertyChanged;
}
this.InvalidateVisual();
}
private void OnDataContextPropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == nameof(ViewModel.Width) || e.PropertyName == nameof(ViewModel.Height)) {
this.InvalidateVisual();
}
}
private void VerifyByteVisualCache() {
if (byteVisualCache.Count != 0) return;
var bytesAsHex = Enumerable.Range(0, 255).Select(i => $"{Hex[i / 0x10]}{Hex[i % 0x10]}");
var text = bytesAsHex.Select(hex => new FormattedText(
hex,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Consolas"),
16,
Brushes.Black,
1.0));
byteVisualCache.AddRange(text);
}
}
}

View File

@@ -0,0 +1,14 @@
<Window x:Class="HavenSoft.Gen3Hex.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hsg3hv="clr-namespace:HavenSoft.Gen3Hex.View"
xmlns:hsg3hvm="clr-namespace:HavenSoft.Gen3Hex.ViewModel"
Title="Gen3Hex" Height="450" Width="800">
<DockPanel>
<hsg3hv:HexContent>
<hsg3hv:HexContent.DataContext>
<hsg3hvm:ViewPort/>
</hsg3hv:HexContent.DataContext>
</hsg3hv:HexContent>
</DockPanel>
</Window>

View File

@@ -1,4 +1,4 @@
namespace HavenSoft.Gen3Hex {
namespace HavenSoft.Gen3Hex.View {
public partial class MainWindow {
public MainWindow() => InitializeComponent();
}

View File

@@ -0,0 +1,5 @@
namespace HavenSoft.Gen3Hex.ViewModel {
public class HexElement {
public byte Value { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System.ComponentModel;
namespace HavenSoft.Gen3Hex.ViewModel {
public class ViewPort : INotifyPropertyChanged {
public int Width { get; set; }
public int Height { get; set; }
public HexElement this[int x, int y] => new HexElement();
public event PropertyChangedEventHandler PropertyChanged;
}
}

View File

@@ -1,4 +1,5 @@
using System.Reflection;
using HavenSoft.Gen3Hex.ViewModel;
using System.Reflection;
using Xunit;
[assembly: AssemblyTitle("HexTests")]
@@ -6,7 +7,15 @@ using Xunit;
namespace HexTests {
public class Tests {
[Fact]
public void TestMethod1() {
public void ViewPortNotifiesOnSizeChange() {
var viewPort = new ViewPort();
var counter = 0;
viewPort.PropertyChanged += (sender, e) => counter++;
viewPort.Width = 12;
viewPort.Height = 50;
Assert.Equal(2, counter);
}
}
}