Skip to content

Commit 912aaec

Browse files
committed
2 parents 4fce168 + a317560 commit 912aaec

13 files changed

+231
-142
lines changed

Source/Controls/BufferEditor/BufferEditor.axaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,30 +103,30 @@
103103
Margin="0,0,10,0" />
104104

105105
<RadioButton GroupName="PayloadType"
106-
IsChecked="{Binding Path=IsText, RelativeSource={RelativeSource AncestorType={x:Type controls:BufferEditor}}}"
106+
IsChecked="{CompiledBinding Path=IsText, RelativeSource={RelativeSource TemplatedParent}}"
107107
Content="Text" />
108108

109109
<RadioButton GroupName="PayloadType"
110-
IsChecked="{Binding Path=IsJson, RelativeSource={RelativeSource AncestorType={x:Type controls:BufferEditor}}}"
110+
IsChecked="{CompiledBinding Path=IsJson, RelativeSource={RelativeSource TemplatedParent}}"
111111
Content="JSON" />
112112

113113
<RadioButton GroupName="PayloadType"
114-
IsChecked="{Binding Path=IsXml, RelativeSource={RelativeSource AncestorType={x:Type controls:BufferEditor}}}"
114+
IsChecked="{CompiledBinding Path=IsXml, RelativeSource={RelativeSource TemplatedParent}}"
115115
Content="XML" />
116116

117117
<RadioButton GroupName="PayloadType"
118-
IsChecked="{Binding Path=IsBase64, RelativeSource={RelativeSource AncestorType={x:Type controls:BufferEditor}}}"
118+
IsChecked="{CompiledBinding Path=IsBase64, RelativeSource={RelativeSource TemplatedParent}}"
119119
Content="Base64" />
120120

121121
<RadioButton GroupName="PayloadType"
122-
IsChecked="{Binding Path=IsPath, RelativeSource={RelativeSource AncestorType={x:Type controls:BufferEditor}}}"
122+
IsChecked="{CompiledBinding Path=IsPath, RelativeSource={RelativeSource TemplatedParent}}"
123123
Content="Path" />
124124
</StackPanel>
125125
</Grid>
126126

127127
<avaloniaEdit:TextEditor Grid.Row="1"
128128
x:Name="TextEditor"
129-
WordWrap="{Binding ElementName=TextWrappingCheckBox, Path=IsChecked}"
129+
WordWrap="{CompiledBinding ElementName=TextWrappingCheckBox, Path=IsChecked}"
130130
Background="Transparent"
131131
Margin="5"
132132
Classes="code_text"

Source/Controls/BufferEditor/BufferEditor.axaml.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,11 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
177177
change.Property == IsXmlProperty ||
178178
change.Property == IsPathProperty)
179179
{
180-
SyncGrammar();
181-
SyncBufferFormat();
180+
if (change.NewValue is true)
181+
{
182+
SyncGrammar();
183+
SyncBufferFormat();
184+
}
182185
}
183186
}
184187

Source/Controls/BufferPreview/BufferPreviewView.axaml

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
Background="{DynamicResource TextControlBackground}">
1616

1717
<!-- The text base previews. -->
18-
<Grid RowDefinitions="Auto,*">
18+
<Grid RowDefinitions="Auto,*"
19+
x:Name="Container">
1920

2021
<!-- Options -->
2122
<Grid Classes="tool_bar"
@@ -27,7 +28,7 @@
2728
<!-- The Text Wrapping button -->
2829
<ToggleButton Classes="tool_bar_button"
2930
IsChecked="True"
30-
IsVisible="{Binding !ShowRaw, RelativeSource={RelativeSource TemplatedParent}}"
31+
IsVisible="{CompiledBinding ShowText, RelativeSource={RelativeSource TemplatedParent}}"
3132
x:Name="TextWrappingCheckBox">
3233
<PathIcon Data="{StaticResource text_wrap_regular}"
3334
ToolTip.Tip="Toggle word wrap" />
@@ -37,7 +38,7 @@
3738

3839
<!-- The Copy button -->
3940
<Button Classes="tool_bar_button"
40-
IsVisible="{Binding !ShowRaw, RelativeSource={RelativeSource TemplatedParent}}"
41+
IsVisible="{CompiledBinding ShowText, RelativeSource={RelativeSource TemplatedParent}}"
4142
x:Name="CopyToClipboardButton">
4243
<PathIcon Data="{StaticResource copy_regular}"
4344
ToolTip.Tip="Copy to clipboard" />
@@ -54,24 +55,34 @@
5455
<!-- The Format selector -->
5556
<StackPanel Grid.Column="2"
5657
Orientation="Horizontal">
58+
59+
<CheckBox IsChecked="{CompiledBinding UseBase64PreDecoding, RelativeSource={RelativeSource TemplatedParent}}"
60+
Content="Unwrap Base64"
61+
Margin="0,0,5,0"
62+
ToolTip.Tip="When active the payload will be unwrapped from a Base64 compatible string" />
63+
64+
<Separator Classes="tool_bar_separator" />
65+
5766
<Label Classes="tool_bar_label"
5867
Content="Format"
59-
Margin="0,0,10,0" />
68+
Margin="5,0,10,0" />
6069
<ComboBox Classes="tool_bar_combo_box"
6170
MinWidth="100"
6271
VerticalAlignment="Stretch"
63-
ItemsSource="{Binding Path=Formats, RelativeSource={RelativeSource TemplatedParent}}"
64-
SelectedItem="{Binding Path=SelectedFormat, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
72+
ItemsSource="{CompiledBinding Path=Formats, RelativeSource={RelativeSource TemplatedParent}, Mode=OneTime}"
73+
SelectedItem="{CompiledBinding Path=SelectedFormat, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
6574
<ComboBox.ItemTemplate>
6675
<DataTemplate>
6776
<TextBlock Text="{Binding Name}" />
6877
</DataTemplate>
6978
</ComboBox.ItemTemplate>
7079
</ComboBox>
80+
81+
7182
</StackPanel>
7283
</Grid>
7384

74-
<avaloniaEdit:TextEditor WordWrap="{Binding ElementName=TextWrappingCheckBox, Path=IsChecked}"
85+
<avaloniaEdit:TextEditor WordWrap="{CompiledBinding ElementName=TextWrappingCheckBox, Path=IsChecked}"
7586
IsReadOnly="True"
7687
x:Name="TextEditor"
7788
Margin="5"
@@ -81,12 +92,17 @@
8192
Grid.Row="1"
8293
ShowLineNumbers="True"
8394
FontFamily="{StaticResource MonospaceFontFamily}"
84-
IsVisible="{Binding !ShowRaw, RelativeSource={RelativeSource TemplatedParent}}" />
95+
IsVisible="{CompiledBinding ShowText, RelativeSource={RelativeSource TemplatedParent}}" />
8596

8697
<controls:HexBox Grid.Row="1"
8798
x:Name="HexBox"
8899
BorderThickness="0"
89-
IsVisible="{Binding ShowRaw, RelativeSource={RelativeSource TemplatedParent}}" />
100+
IsVisible="{CompiledBinding ShowRaw, RelativeSource={RelativeSource TemplatedParent}}" />
101+
102+
<Viewbox Grid.Row="1"
103+
Stretch="Uniform"
104+
x:Name="PictureBox"
105+
IsVisible="{CompiledBinding ShowPicture, RelativeSource={RelativeSource TemplatedParent}}" />
90106
</Grid>
91107
</Border>
92108
</ControlTemplate>

Source/Controls/BufferPreview/BufferPreviewView.axaml.cs

Lines changed: 106 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Avalonia.Controls;
1212
using Avalonia.Controls.Primitives;
1313
using Avalonia.Interactivity;
14+
using Avalonia.Media.Imaging;
1415
using Avalonia.Platform.Storage;
1516
using Avalonia.Threading;
1617
using AvaloniaEdit;
@@ -38,13 +39,18 @@ public sealed class BufferInspectorView : TemplatedControl
3839

3940
public static readonly StyledProperty<bool> ShowRawProperty = AvaloniaProperty.Register<BufferInspectorView, bool>(nameof(ShowRaw));
4041

42+
public static readonly StyledProperty<bool> ShowTextProperty = AvaloniaProperty.Register<BufferInspectorView, bool>(nameof(ShowText));
43+
44+
public static readonly StyledProperty<bool> ShowPictureProperty = AvaloniaProperty.Register<BufferInspectorView, bool>(nameof(ShowPicture));
45+
46+
public static readonly StyledProperty<bool> UseBase64PreDecodingProperty = AvaloniaProperty.Register<BufferInspectorView, bool>(nameof(UseBase64PreDecoding));
47+
4148
public static readonly StyledProperty<string?> SelectedFormatNameProperty = AvaloniaProperty.Register<BufferInspectorView, string?>(nameof(SelectedFormatName), "UTF-8");
4249

4350
readonly RegistryOptions _textEditorRegistryOptions = new(ThemeName.Dark);
44-
45-
string _content = string.Empty;
4651
Button? _copyToClipboardButton;
4752
HexBox? _hexBox;
53+
Viewbox? _pictureBox;
4854
Button? _saveToFileButton;
4955
TextEditor? _textEditor;
5056
TextMate.Installation? _textMateInstallation;
@@ -103,7 +109,7 @@ public string? SelectedFormatName
103109
return JsonSerializerService.Instance?.Format(json) ?? string.Empty;
104110
}),
105111

106-
112+
new BufferConverter("Picture", null, _ => "PICTURE"), // Special case!
107113
new BufferConverter("RAW", null, _ => "RAW"), // Special case!
108114
new BufferConverter("Unicode", null, b => Encoding.Unicode.GetString(b)),
109115
new BufferConverter("UTF-8", null, b => Encoding.UTF8.GetString(b)),
@@ -117,42 +123,78 @@ public string? SelectedFormatName
117123
})
118124
];
119125

126+
public bool ShowPicture
127+
{
128+
get => GetValue(ShowPictureProperty);
129+
set => SetValue(ShowPictureProperty, value);
130+
}
131+
120132
public bool ShowRaw
121133
{
122134
get => GetValue(ShowRawProperty);
123135
set => SetValue(ShowRawProperty, value);
124136
}
125137

138+
public bool ShowText
139+
{
140+
get => GetValue(ShowTextProperty);
141+
set => SetValue(ShowTextProperty, value);
142+
}
143+
144+
public bool UseBase64PreDecoding
145+
{
146+
get => GetValue(UseBase64PreDecodingProperty);
147+
set => SetValue(UseBase64PreDecodingProperty, value);
148+
}
149+
126150
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
127151
{
128152
base.OnApplyTemplate(e);
129153

130154
_hexBox = (HexBox)this.GetTemplateChild("HexBox");
155+
_pictureBox = (Viewbox)this.GetTemplateChild("PictureBox");
131156

132157
_textEditor = (TextEditor)this.GetTemplateChild("TextEditor");
133158
_textMateInstallation = _textEditor.InstallTextMate(_textEditorRegistryOptions);
134-
SyncTextEditor();
135159

136160
_copyToClipboardButton = (Button)this.GetTemplateChild("CopyToClipboardButton");
137161
_copyToClipboardButton.Click += OnCopyToClipboard;
138162

139163
_saveToFileButton = (Button)this.GetTemplateChild("SaveToFileButton");
140164
_saveToFileButton.Click += OnSaveToFile;
141-
ReadBuffer();
165+
166+
Sync();
142167
}
143168

144169
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
145170
{
146171
base.OnPropertyChanged(change);
147172

148-
if (change.Property == BufferProperty || change.Property == SelectedFormatProperty)
173+
if (change.Property == SelectedFormatProperty)
149174
{
150-
ReadBuffer();
175+
if (string.Equals(SelectedFormat?.Name, "RAW"))
176+
{
177+
ShowRaw = true;
178+
ShowText = false;
179+
ShowPicture = false;
180+
}
181+
else if (string.Equals(SelectedFormat?.Name, "Picture"))
182+
{
183+
ShowPicture = true;
184+
ShowText = false;
185+
ShowRaw = false;
186+
}
187+
else
188+
{
189+
ShowText = true;
190+
ShowPicture = false;
191+
ShowRaw = false;
192+
}
151193
}
152194

153-
if (change.Property == SelectedFormatProperty)
195+
if (change.Property == UseBase64PreDecodingProperty || change.Property == SelectedFormatProperty || change.Property == BufferProperty)
154196
{
155-
ShowRaw = ReferenceEquals(SelectedFormat?.Name, "RAW");
197+
Sync();
156198
}
157199

158200
if (change.Property == SelectedFormatNameProperty)
@@ -163,10 +205,10 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
163205

164206
void OnCopyToClipboard(object? sender, RoutedEventArgs e)
165207
{
166-
if (!string.IsNullOrEmpty(_content))
208+
if (!string.IsNullOrEmpty(_textEditor!.Text))
167209
{
168210
var clipboard = TopLevel.GetTopLevel(this)?.Clipboard;
169-
_ = clipboard?.SetTextAsync(_content);
211+
_ = clipboard?.SetTextAsync(_textEditor.Text);
170212
}
171213
}
172214

@@ -210,33 +252,6 @@ void OnSaveToFile(object? sender, RoutedEventArgs e)
210252
});
211253
}
212254

213-
void ReadBuffer()
214-
{
215-
var format = SelectedFormat;
216-
if (format == null)
217-
{
218-
throw new InvalidOperationException();
219-
}
220-
221-
if ((Buffer?.Length ?? 0) == 0)
222-
{
223-
_content = string.Empty;
224-
}
225-
else
226-
{
227-
try
228-
{
229-
_content = format.Convert(Buffer!);
230-
}
231-
catch (Exception exception)
232-
{
233-
_content = $"<{exception.Message}>";
234-
}
235-
}
236-
237-
SyncTextEditor();
238-
}
239-
240255
void SelectFormat()
241256
{
242257
if (string.IsNullOrEmpty(SelectedFormatName))
@@ -254,9 +269,9 @@ void SelectFormat()
254269
}
255270
}
256271

257-
void SyncTextEditor()
272+
void Sync()
258273
{
259-
if (_textEditor == null || _hexBox == null)
274+
if (_textEditor == null || _hexBox == null || _pictureBox == null)
260275
{
261276
return;
262277
}
@@ -266,16 +281,61 @@ void SyncTextEditor()
266281
return;
267282
}
268283

269-
_textMateInstallation?.SetGrammar(SelectedFormat.Grammar);
270-
271-
// It is important to set the content after the grammar so that
272-
// the highlighting gets applied properly!
273-
_textEditor.Text = _content;
284+
var buffer = Buffer ?? Array.Empty<byte>();
285+
if (UseBase64PreDecoding)
286+
{
287+
try
288+
{
289+
buffer = Convert.FromBase64String(Encoding.ASCII.GetString(buffer));
290+
}
291+
catch
292+
{
293+
// Go ahead if decoding did not work. It is probably not required.
294+
}
295+
}
274296

275297
if (SelectedFormat.Name == "RAW")
276298
{
277299
// Only fill the data of the hex box when it is actually used!
278-
_hexBox.Value = Buffer;
300+
_hexBox.Value = buffer;
301+
}
302+
else if (SelectedFormat.Name == "Picture")
303+
{
304+
try
305+
{
306+
if (_pictureBox.Child is Image existingImage)
307+
{
308+
((Bitmap)existingImage.Source!).Dispose();
309+
}
310+
311+
_pictureBox.Child = new Image
312+
{
313+
Source = new Bitmap(new MemoryStream(buffer))
314+
};
315+
}
316+
catch
317+
{
318+
// Ignore. We may can set a picture here indicating that the format is not supported.
319+
_pictureBox.Child = null;
320+
}
321+
}
322+
else
323+
{
324+
string text;
325+
try
326+
{
327+
text = SelectedFormat.Convert(buffer);
328+
}
329+
catch (Exception exception)
330+
{
331+
text = exception.ToString();
332+
}
333+
334+
_textMateInstallation?.SetGrammar(SelectedFormat.Grammar);
335+
336+
// It is important to set the content after the grammar so that
337+
// the highlighting gets applied properly!
338+
_textEditor.Text = text;
279339
}
280340
}
281341
}

0 commit comments

Comments
 (0)