Skip to content

Commit b8178bb

Browse files
committed
Add options toolbar in WPF viewer
1 parent 1eeffd4 commit b8178bb

7 files changed

+161
-45
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System.ComponentModel;
2+
using PropertyChanged;
3+
4+
namespace ProtoUntyped.Viewer
5+
{
6+
[AddINotifyPropertyChangedInterface]
7+
public class DecodeOptionsViewModel : INotifyPropertyChanged
8+
{
9+
public event PropertyChangedEventHandler PropertyChanged;
10+
11+
public bool DecodeGuid { get; set; } = true;
12+
public bool DecodeDateTime { get; set; } = true;
13+
public bool DecodeTimeSpan { get; set; } = true;
14+
public bool DecodeDecimal { get; set; } = true;
15+
16+
public ProtoDecodeOptions ProtoDecodeOptions => new()
17+
{
18+
DecodeGuid = DecodeGuid,
19+
DecodeDateTime = DecodeDateTime,
20+
DecodeTimeSpan = DecodeTimeSpan,
21+
DecodeDecimal = DecodeDecimal,
22+
};
23+
}
24+
}
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
3+
<PropertyChanged />
4+
</Weavers>
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3+
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
4+
<xs:element name="Weavers">
5+
<xs:complexType>
6+
<xs:all>
7+
<xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
8+
<xs:complexType>
9+
<xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
10+
<xs:annotation>
11+
<xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
12+
</xs:annotation>
13+
</xs:attribute>
14+
<xs:attribute name="TriggerDependentProperties" type="xs:boolean">
15+
<xs:annotation>
16+
<xs:documentation>Used to control if the Dependent properties feature is enabled.</xs:documentation>
17+
</xs:annotation>
18+
</xs:attribute>
19+
<xs:attribute name="EnableIsChangedProperty" type="xs:boolean">
20+
<xs:annotation>
21+
<xs:documentation>Used to control if the IsChanged property feature is enabled.</xs:documentation>
22+
</xs:annotation>
23+
</xs:attribute>
24+
<xs:attribute name="EventInvokerNames" type="xs:string">
25+
<xs:annotation>
26+
<xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
27+
</xs:annotation>
28+
</xs:attribute>
29+
<xs:attribute name="CheckForEquality" type="xs:boolean">
30+
<xs:annotation>
31+
<xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
32+
</xs:annotation>
33+
</xs:attribute>
34+
<xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
35+
<xs:annotation>
36+
<xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
37+
</xs:annotation>
38+
</xs:attribute>
39+
<xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
40+
<xs:annotation>
41+
<xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
42+
</xs:annotation>
43+
</xs:attribute>
44+
<xs:attribute name="SuppressWarnings" type="xs:boolean">
45+
<xs:annotation>
46+
<xs:documentation>Used to turn off build warnings from this weaver.</xs:documentation>
47+
</xs:annotation>
48+
</xs:attribute>
49+
<xs:attribute name="SuppressOnPropertyNameChangedWarning" type="xs:boolean">
50+
<xs:annotation>
51+
<xs:documentation>Used to turn off build warnings about mismatched On_PropertyName_Changed methods.</xs:documentation>
52+
</xs:annotation>
53+
</xs:attribute>
54+
</xs:complexType>
55+
</xs:element>
56+
</xs:all>
57+
<xs:attribute name="VerifyAssembly" type="xs:boolean">
58+
<xs:annotation>
59+
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
60+
</xs:annotation>
61+
</xs:attribute>
62+
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
63+
<xs:annotation>
64+
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
65+
</xs:annotation>
66+
</xs:attribute>
67+
<xs:attribute name="GenerateXsd" type="xs:boolean">
68+
<xs:annotation>
69+
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
70+
</xs:annotation>
71+
</xs:attribute>
72+
</xs:complexType>
73+
</xs:element>
74+
</xs:schema>
+23-20
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,31 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.ComponentModel;
43
using System.Linq;
5-
using System.Runtime.CompilerServices;
4+
using System.Text.Json;
65
using AutoFixture;
76
using AutoFixture.Kernel;
7+
using PropertyChanged;
88
using ProtoUntyped.Viewer.Messages;
99

1010
namespace ProtoUntyped.Viewer
1111
{
12-
public class MainViewModel : INotifyPropertyChanged
12+
[AddINotifyPropertyChangedInterface]
13+
public class MainViewModel
1314
{
14-
private MessageViewModel _selectedMessage;
15-
1615
public MainViewModel()
1716
{
1817
Messages = GenerateMessages();
18+
Options.PropertyChanged += (_, _) => ComputeProtoObject();
1919
}
20-
21-
public event PropertyChangedEventHandler PropertyChanged;
2220

23-
public List<MessageViewModel> Messages { get; set; }
24-
25-
public MessageViewModel SelectedMessage
26-
{
27-
get => _selectedMessage;
28-
set
29-
{
30-
if (Equals(value, _selectedMessage))
31-
return;
32-
_selectedMessage = value;
33-
PropertyChanged?.Invoke(this, new(nameof(SelectedMessage)));
34-
}
35-
}
21+
public DecodeOptionsViewModel Options { get; } = new();
22+
public List<MessageViewModel> Messages { get; }
23+
public MessageViewModel SelectedMessage { get; set; }
24+
25+
public ProtoObject ProtoObject { get; private set; }
26+
27+
public string ProtoObjectJson => ProtoObject != null ? JsonSerializer.Serialize(ProtoObject.ToFieldDictionary(), new JsonSerializerOptions { WriteIndented = true }) : null;
28+
public string ProtoObjectString => ProtoObject?.ToString();
3629

3730
private static List<MessageViewModel> GenerateMessages()
3831
{
@@ -52,5 +45,15 @@ object CreateMessage(Type type)
5245
return context.Resolve(new SeededRequest(type, null));
5346
}
5447
}
48+
49+
private void OnSelectedMessageChanged()
50+
{
51+
ComputeProtoObject();
52+
}
53+
54+
private void ComputeProtoObject()
55+
{
56+
ProtoObject = SelectedMessage != null ? ProtoObject.Decode(SelectedMessage.ProtoBytes, Options.ProtoDecodeOptions) : null;
57+
}
5558
}
5659
}

src/ProtoUntyped.Viewer/MainWindow.xaml

+31-19
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,35 @@
77
mc:Ignorable="d"
88
Title="MainWindow" Height="1000" Width="1000"
99
d:DataContext="{d:DesignInstance Type={x:Type local:MainViewModel}}">
10-
<Grid>
11-
<Grid.ColumnDefinitions>
12-
<ColumnDefinition />
13-
<ColumnDefinition />
14-
</Grid.ColumnDefinitions>
15-
<Grid.RowDefinitions>
16-
<RowDefinition />
17-
<RowDefinition />
18-
<RowDefinition />
19-
</Grid.RowDefinitions>
20-
<DataGrid ItemsSource="{Binding Messages}" AutoGenerateColumns="False" Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" SelectedItem="{Binding SelectedMessage}">
21-
<DataGrid.Columns>
22-
<DataGridTextColumn Header="Message" Binding="{Binding TypeName}" Width="*"></DataGridTextColumn>
23-
</DataGrid.Columns>
24-
</DataGrid>
25-
<TextBox IsReadOnly="true" Grid.Row="0" Grid.Column="1" Text="{Binding SelectedMessage.MessageJson, Mode=OneWay}" />
26-
<TextBox IsReadOnly="true" Grid.Row="1" Grid.Column="1" Text="{Binding SelectedMessage.ProtoObjectJson, Mode=OneWay}" />
27-
<TextBox IsReadOnly="true" Grid.Row="2" Grid.Column="1" Text="{Binding SelectedMessage.ProtoObjectString, Mode=OneWay}" />
28-
</Grid>
10+
<DockPanel LastChildFill="True">
11+
<ToolBarTray DockPanel.Dock="Top">
12+
<ToolBar ToolBarTray.IsLocked="True" Padding="5">
13+
<StackPanel Orientation="Horizontal">
14+
<CheckBox IsChecked="{Binding Options.DecodeGuid}" Content="Decode Guid" Margin="5 0" />
15+
<CheckBox IsChecked="{Binding Options.DecodeDateTime}" Content="Decode DateTime" Margin="5 0" />
16+
<CheckBox IsChecked="{Binding Options.DecodeTimeSpan}" Content="Decode TimeSpan" Margin="5 0" />
17+
<CheckBox IsChecked="{Binding Options.DecodeDecimal}" Content="Decode decimal" Margin="5 0" />
18+
</StackPanel>
19+
</ToolBar>
20+
</ToolBarTray>
21+
<Grid>
22+
<Grid.ColumnDefinitions>
23+
<ColumnDefinition />
24+
<ColumnDefinition />
25+
</Grid.ColumnDefinitions>
26+
<Grid.RowDefinitions>
27+
<RowDefinition />
28+
<RowDefinition />
29+
<RowDefinition />
30+
</Grid.RowDefinitions>
31+
<DataGrid ItemsSource="{Binding Messages}" AutoGenerateColumns="False" Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" SelectedItem="{Binding SelectedMessage}">
32+
<DataGrid.Columns>
33+
<DataGridTextColumn Header="Message" Binding="{Binding TypeName}" Width="*"></DataGridTextColumn>
34+
</DataGrid.Columns>
35+
</DataGrid>
36+
<TextBox IsReadOnly="true" Grid.Row="0" Grid.Column="1" Text="{Binding SelectedMessage.MessageJson, Mode=OneWay}" />
37+
<TextBox IsReadOnly="true" Grid.Row="1" Grid.Column="1" Text="{Binding ProtoObjectJson, Mode=OneWay}" />
38+
<TextBox IsReadOnly="true" Grid.Row="2" Grid.Column="1" Text="{Binding ProtoObjectString, Mode=OneWay}" />
39+
</Grid>
40+
</DockPanel>
2941
</Window>
+4-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
using System;
21
using System.IO;
32
using System.Text.Json;
4-
using System.Windows.Documents;
3+
using PropertyChanged;
54
using ProtoBuf;
65

76
namespace ProtoUntyped.Viewer
87
{
8+
[AddINotifyPropertyChangedInterface]
99
public class MessageViewModel
1010
{
1111
public MessageViewModel(object message)
@@ -15,13 +15,11 @@ public MessageViewModel(object message)
1515

1616
using var stream = new MemoryStream();
1717
Serializer.Serialize(stream, message);
18-
ProtoObject = ProtoObject.Decode(stream.GetBuffer().AsMemory(0, (int)stream.Length), new ProtoDecodeOptions { DecodeGuid = true, DecodeDateTime = true, DecodeTimeSpan = true });
18+
ProtoBytes = stream.ToArray();
1919
}
2020

2121
public string TypeName { get; set; }
2222
public string MessageJson { get; set; }
23-
public ProtoObject ProtoObject { get; set; }
24-
public string ProtoObjectJson => JsonSerializer.Serialize(ProtoObject.ToFieldDictionary(), new JsonSerializerOptions { WriteIndented = true });
25-
public string ProtoObjectString => ProtoObject.ToString();
23+
public byte[] ProtoBytes { get; set; }
2624
}
2725
}

src/ProtoUntyped.Viewer/ProtoUntyped.Viewer.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
<ItemGroup>
1414
<PackageReference Include="AutoFixture" Version="4.15.0" />
15+
<PackageReference Include="PropertyChanged.Fody" Version="3.3.1" PrivateAssets="all" />
1516
</ItemGroup>
1617

1718
</Project>

0 commit comments

Comments
 (0)