Add project restore files and NuGet cache for GsaViewer
- Created project.nuget.cache to store NuGet package cache information. - Added project.packagespec.json to define project restore settings and dependencies. - Included rider.project.restore.info for Rider IDE integration.
This commit is contained in:
204
GsaEditor/Helpers/Dialogs.cs
Normal file
204
GsaEditor/Helpers/Dialogs.cs
Normal file
@ -0,0 +1,204 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
|
||||
namespace GsaEditor.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Provides simple dialog utilities (confirm, message, input) using programmatically-created Avalonia windows.
|
||||
/// No third-party controls or custom themes are used.
|
||||
/// </summary>
|
||||
public static class Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows a confirmation dialog with Yes/No buttons.
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent window.</param>
|
||||
/// <param name="title">Dialog title.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <returns>True if the user clicked Yes, false otherwise.</returns>
|
||||
public static async Task<bool> ConfirmAsync(Window parent, string title, string message)
|
||||
{
|
||||
var result = false;
|
||||
|
||||
var dialog = new Window
|
||||
{
|
||||
Title = title,
|
||||
Width = 420,
|
||||
Height = 170,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
CanResize = false,
|
||||
ShowInTaskbar = false
|
||||
};
|
||||
|
||||
var messageBlock = new TextBlock
|
||||
{
|
||||
Text = message,
|
||||
TextWrapping = Avalonia.Media.TextWrapping.Wrap,
|
||||
Margin = new Thickness(0, 0, 0, 15)
|
||||
};
|
||||
|
||||
var yesButton = new Button
|
||||
{
|
||||
Content = "Yes",
|
||||
Width = 80,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
yesButton.Click += (_, _) =>
|
||||
{
|
||||
result = true;
|
||||
dialog.Close();
|
||||
};
|
||||
|
||||
var noButton = new Button
|
||||
{
|
||||
Content = "No",
|
||||
Width = 80,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
noButton.Click += (_, _) =>
|
||||
{
|
||||
result = false;
|
||||
dialog.Close();
|
||||
};
|
||||
|
||||
var buttonPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
Spacing = 10,
|
||||
Children = { yesButton, noButton }
|
||||
};
|
||||
|
||||
dialog.Content = new StackPanel
|
||||
{
|
||||
Margin = new Thickness(20),
|
||||
Spacing = 5,
|
||||
Children = { messageBlock, buttonPanel }
|
||||
};
|
||||
|
||||
await dialog.ShowDialog(parent);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows a simple message dialog with an OK button.
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent window.</param>
|
||||
/// <param name="title">Dialog title.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
public static async Task ShowMessageAsync(Window parent, string title, string message)
|
||||
{
|
||||
var dialog = new Window
|
||||
{
|
||||
Title = title,
|
||||
Width = 420,
|
||||
Height = 180,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
CanResize = false,
|
||||
ShowInTaskbar = false
|
||||
};
|
||||
|
||||
var messageBlock = new TextBlock
|
||||
{
|
||||
Text = message,
|
||||
TextWrapping = Avalonia.Media.TextWrapping.Wrap,
|
||||
Margin = new Thickness(0, 0, 0, 15)
|
||||
};
|
||||
|
||||
var okButton = new Button
|
||||
{
|
||||
Content = "OK",
|
||||
Width = 80,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
okButton.Click += (_, _) => dialog.Close();
|
||||
|
||||
dialog.Content = new StackPanel
|
||||
{
|
||||
Margin = new Thickness(20),
|
||||
Spacing = 5,
|
||||
Children = { messageBlock, okButton }
|
||||
};
|
||||
|
||||
await dialog.ShowDialog(parent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows an input dialog with a text box, OK and Cancel buttons.
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent window.</param>
|
||||
/// <param name="title">Dialog title.</param>
|
||||
/// <param name="prompt">Prompt text shown above the input.</param>
|
||||
/// <param name="defaultValue">Default value in the text box.</param>
|
||||
/// <returns>The entered string, or null if cancelled.</returns>
|
||||
public static async Task<string?> InputAsync(Window parent, string title, string prompt, string defaultValue = "")
|
||||
{
|
||||
string? result = null;
|
||||
|
||||
var dialog = new Window
|
||||
{
|
||||
Title = title,
|
||||
Width = 450,
|
||||
Height = 180,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
CanResize = false,
|
||||
ShowInTaskbar = false
|
||||
};
|
||||
|
||||
var promptBlock = new TextBlock
|
||||
{
|
||||
Text = prompt,
|
||||
Margin = new Thickness(0, 0, 0, 5)
|
||||
};
|
||||
|
||||
var textBox = new TextBox
|
||||
{
|
||||
Text = defaultValue,
|
||||
Margin = new Thickness(0, 0, 0, 10)
|
||||
};
|
||||
|
||||
var okButton = new Button
|
||||
{
|
||||
Content = "OK",
|
||||
Width = 80,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
okButton.Click += (_, _) =>
|
||||
{
|
||||
result = textBox.Text;
|
||||
dialog.Close();
|
||||
};
|
||||
|
||||
var cancelButton = new Button
|
||||
{
|
||||
Content = "Cancel",
|
||||
Width = 80,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
cancelButton.Click += (_, _) =>
|
||||
{
|
||||
result = null;
|
||||
dialog.Close();
|
||||
};
|
||||
|
||||
var buttonPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
Spacing = 10,
|
||||
Children = { okButton, cancelButton }
|
||||
};
|
||||
|
||||
dialog.Content = new StackPanel
|
||||
{
|
||||
Margin = new Thickness(20),
|
||||
Spacing = 5,
|
||||
Children = { promptBlock, textBox, buttonPanel }
|
||||
};
|
||||
|
||||
await dialog.ShowDialog(parent);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
59
GsaEditor/Helpers/HexDumper.cs
Normal file
59
GsaEditor/Helpers/HexDumper.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System.Text;
|
||||
|
||||
namespace GsaEditor.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Produces a classic hex + ASCII dump string from a byte array.
|
||||
/// </summary>
|
||||
public static class HexDumper
|
||||
{
|
||||
/// <summary>
|
||||
/// Formats a byte array as a hex dump with offset, hex values, and printable ASCII characters.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to dump.</param>
|
||||
/// <param name="maxBytes">Maximum number of bytes to include in the dump.</param>
|
||||
/// <returns>A formatted hex dump string.</returns>
|
||||
public static string Dump(byte[] data, int maxBytes = 512)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
int length = Math.Min(data.Length, maxBytes);
|
||||
const int bytesPerLine = 16;
|
||||
|
||||
for (int offset = 0; offset < length; offset += bytesPerLine)
|
||||
{
|
||||
// Offset column
|
||||
sb.Append($"{offset:X8} ");
|
||||
|
||||
int lineLen = Math.Min(bytesPerLine, length - offset);
|
||||
|
||||
// Hex columns
|
||||
for (int i = 0; i < bytesPerLine; i++)
|
||||
{
|
||||
if (i < lineLen)
|
||||
sb.Append($"{data[offset + i]:X2} ");
|
||||
else
|
||||
sb.Append(" ");
|
||||
|
||||
if (i == 7) sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Append(' ');
|
||||
|
||||
// ASCII column
|
||||
for (int i = 0; i < lineLen; i++)
|
||||
{
|
||||
byte b = data[offset + i];
|
||||
sb.Append(b >= 0x20 && b < 0x7F ? (char)b : '.');
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
if (data.Length > maxBytes)
|
||||
{
|
||||
sb.AppendLine($"... ({data.Length - maxBytes} more bytes)");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user