1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Meta - Fix remaing warnings in non-WPF projects

This commit is contained in:
Robert 2022-01-02 23:56:06 +01:00
parent 1c15fbe983
commit 353eec2529
37 changed files with 539 additions and 172 deletions

View File

@ -129,15 +129,33 @@
<member name="F:Artemis.UI.Shared.Controls.HotkeyBox.HotkeyProperty">
<summary>
Gets or sets the currently displayed icon as either a <see cref="T:Material.Icons.MaterialIconKind" /> or an <see cref="T:System.Uri" />
pointing
to an SVG
pointing to an SVG
</summary>
</member>
<member name="F:Artemis.UI.Shared.Controls.HotkeyBox.WatermarkProperty">
<summary>
Gets or sets the watermark of the hotkey box when it is empty.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Controls.HotkeyBox.UseFloatingWatermarkProperty">
<summary>
Gets or sets a boolean indicating whether the watermark should float above the hotkey box when it is not empty.
</summary>
</member>
<member name="P:Artemis.UI.Shared.Controls.HotkeyBox.Hotkey">
<summary>
Gets or sets the currently displayed icon as either a <see cref="T:Material.Icons.MaterialIconKind" /> or an <see cref="T:System.Uri" />
pointing
to an SVG
pointing to an SVG
</summary>
</member>
<member name="P:Artemis.UI.Shared.Controls.HotkeyBox.Watermark">
<summary>
Gets or sets the watermark of the hotkey box when it is empty.
</summary>
</member>
<member name="P:Artemis.UI.Shared.Controls.HotkeyBox.UseFloatingWatermark">
<summary>
Gets or sets a boolean indicating whether the watermark should float above the hotkey box when it is not empty.
</summary>
</member>
<member name="M:Artemis.UI.Shared.Controls.NoInputTextBox.OnKeyDown(Avalonia.Input.KeyEventArgs)">
@ -704,6 +722,16 @@
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelVisualizationViewModel.Dispose">
<inheritdoc />
</member>
<member name="T:Artemis.UI.Shared.DefaultTypes.DataModel.Display.DefaultDataModelDisplayView">
<summary>
Represents a default data model display view.
</summary>
</member>
<member name="M:Artemis.UI.Shared.DefaultTypes.DataModel.Display.DefaultDataModelDisplayView.#ctor">
<summary>
Creates a new instance of the <see cref="T:Artemis.UI.Shared.DefaultTypes.DataModel.Display.DefaultDataModelDisplayView" /> class.
</summary>
</member>
<member name="T:Artemis.UI.Shared.DefaultTypes.DataModel.Display.DefaultDataModelDisplayViewModel">
<summary>
Represents the default data model display view model that is used when no display viewmodel specific for the type
@ -824,6 +852,127 @@
Occurs when the the window hosting the view model should close
</summary>
</member>
<member name="T:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder">
<summary>
Represents a builder that can be used to create Fluent UI dialogs.
</summary>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder.WithTitle(System.String)">
<summary>
Changes the title of the dialog.
</summary>
<param name="title">The new title.</param>
<returns>The builder that can be used to further build the dialog.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder.WithContent(System.String)">
<summary>
Changes the content of the dialog.
</summary>
<param name="content">The new content.</param>
<returns>The builder that can be used to further build the dialog.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder.WithDefaultButton(Artemis.UI.Shared.Services.Builders.ContentDialogButton)">
<summary>
Changes the default button of the dialog that is pressed on enter.
</summary>
<param name="defaultButton">The default button.</param>
<returns>The builder that can be used to further build the dialog.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder.HavingPrimaryButton(System.Action{Artemis.UI.Shared.Services.Builders.ContentDialogButtonBuilder})">
<summary>
Changes the primary button of the dialog.
</summary>
<param name="configure">An action to configure the button.</param>
<returns>The builder that can be used to further build the dialog.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder.HavingSecondaryButton(System.Action{Artemis.UI.Shared.Services.Builders.ContentDialogButtonBuilder})">
<summary>
Changes the secondary button of the dialog.
</summary>
<param name="configure">An action to configure the button.</param>
<returns>The builder that can be used to further build the dialog.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder.WithCloseButtonText(System.String)">
<summary>
Changes the text of the close button of the dialog.
</summary>
<param name="text">The new text.</param>
<returns>The builder that can be used to further build the dialog.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder.WithViewModel``1(``0@,System.ValueTuple{System.String,System.Object}[])">
<summary>
Changes the view model of the content dialog, hosting it inside the dialog.
</summary>
<typeparam name="T">The type of the view model to host.</typeparam>
<param name="viewModel">The resulting view model.</param>
<param name="parameters">Optional parameters to pass to the constructor of the view model, case and order sensitive.</param>
<returns>The builder that can be used to further build the dialog.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogBuilder.ShowAsync">
<summary>
Asynchronously shows the content dialog.
</summary>
<returns>A task containing the result of the content dialog.</returns>
<exception cref="T:Artemis.UI.Shared.ArtemisSharedUIException">Thrown when the parent window does not contain a panel at its root.</exception>
</member>
<member name="T:Artemis.UI.Shared.Services.Builders.ContentDialogButton">
<summary>
Represents a content dialog button.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Services.Builders.ContentDialogButton.None">
<summary>
No button.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Services.Builders.ContentDialogButton.Primary">
<summary>
The primary button.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Services.Builders.ContentDialogButton.Secondary">
<summary>
The secondary button.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Services.Builders.ContentDialogButton.Close">
<summary>
The close button.
</summary>
</member>
<member name="T:Artemis.UI.Shared.Services.Builders.ContentDialogButtonBuilder">
<summary>
Represents a builder that can be used to create buttons inside content dialogs.
</summary>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogButtonBuilder.WithText(System.String)">
<summary>
Changes text message of the button.
</summary>
<param name="text">The new text.</param>
<returns>The notification builder that can be used to further build the button.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogButtonBuilder.WithAction(System.Action)">
<summary>
Changes action that is called when the button is clicked.
</summary>
<param name="action">The action to call when the button is clicked.</param>
<returns>The builder that can be used to further build the button.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogButtonBuilder.WithCommand(System.Windows.Input.ICommand)">
<summary>
Changes command that is called when the button is clicked.
</summary>
<param name="command">The command to call when the button is clicked.</param>
<returns>The builder that can be used to further build the button.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.ContentDialogButtonBuilder.WithCommandParameter(System.Object)">
<summary>
Changes parameter of the command that is called when the button is clicked.
</summary>
<param name="commandParameter">The parameter of the command to call when the button is clicked.</param>
<returns>The builder that can be used to further build the button.</returns>
</member>
<member name="T:Artemis.UI.Shared.Services.Builders.FileDialogFilterBuilder">
<summary>
Represents a builder that can create a <see cref="T:Avalonia.Controls.FileDialogFilter" />.
@ -894,7 +1043,7 @@
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.NotificationBuilder.HavingButton(System.Action{Artemis.UI.Shared.Services.Builders.NotificationButtonBuilder})">
<summary>
Changes the action button of the dialog.
Changes the action button of the notification.
</summary>
<param name="configure">An action to configure the button.</param>
<returns>The notification builder that can be used to further build the notification.</returns>
@ -921,20 +1070,58 @@
Changes action that is called when the button is clicked.
</summary>
<param name="action">The action to call when the button is clicked.</param>
<returns>The notification builder that can be used to further build the button.</returns>
<returns>The builder that can be used to further build the button.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.NotificationButtonBuilder.WithCommand(System.Windows.Input.ICommand)">
<summary>
Changes command that is called when the button is clicked.
</summary>
<param name="command">The command to call when the button is clicked.</param>
<returns>The notification builder that can be used to further build the button.</returns>
<returns>The builder that can be used to further build the button.</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.NotificationButtonBuilder.WithCommandParameter(System.Object)">
<summary>
Changes parameter of the command that is called when the button is clicked.
</summary>
<param name="commandParameter">The parameter of the command to call when the button is clicked.</param>
<returns>The builder that can be used to further build the button.</returns>
</member>
<member name="T:Artemis.UI.Shared.Services.Builders.NotificationSeverity">
<summary>
Represents a severity of a notification.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Services.Builders.NotificationSeverity.Informational">
<summary>
A severity for informational messages.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Services.Builders.NotificationSeverity.Success">
<summary>
A severity for success messages.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Services.Builders.NotificationSeverity.Warning">
<summary>
A severity for warning messages.
</summary>
</member>
<member name="F:Artemis.UI.Shared.Services.Builders.NotificationSeverity.Error">
<summary>
A severity for error messages.
</summary>
</member>
<member name="T:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder">
<summary>
Represents a builder that can create a <see cref="T:Avalonia.Controls.OpenFileDialog" />.
</summary>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder.#ctor(Avalonia.Controls.Window)">
<summary>
Creates a new instance of the <see cref="T:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder"/> class.
</summary>
<param name="parent">The parent window that will host the dialog.</param>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder.WithAllowMultiple">
<summary>
Indicate that the user can select multiple files.
@ -962,7 +1149,7 @@
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder.ShowAsync">
<summary>
Shows the file dialog
Asynchronously shows the file dialog.
</summary>
<returns>
A task that on completion returns an array containing the full path to the selected
@ -974,6 +1161,12 @@
Represents a builder that can create a <see cref="T:Avalonia.Controls.SaveFileDialog" />.
</summary>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.SaveFileDialogBuilder.#ctor(Avalonia.Controls.Window)">
<summary>
Creates a new instance of the <see cref="T:Artemis.UI.Shared.Services.Builders.SaveFileDialogBuilder" /> class.
</summary>
<param name="parent">The parent window that will host the notification.</param>
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.SaveFileDialogBuilder.WithTitle(System.String)">
<summary>
Set the title of the dialog
@ -1001,7 +1194,7 @@
</member>
<member name="M:Artemis.UI.Shared.Services.Builders.SaveFileDialogBuilder.ShowAsync">
<summary>
Shows the save file dialog.
Asynchronously shows the save file dialog.
</summary>
<returns>
A task that on completion contains the full path of the save location, or null if the
@ -1111,9 +1304,26 @@
<param name="updateCallback">A function to call whenever the input was updated (submitted or not)</param>
<returns>The most appropriate input view model for the provided <paramref name="propertyType" /></returns>
</member>
<member name="T:Artemis.UI.Shared.Services.Interfaces.INotificationService">
<summary>
A service that can be used to create notifications in either the application or on the desktop.
</summary>
</member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.INotificationService.CreateNotification">
<summary>
Creates an in-app notification using a builder.
</summary>
<returns>A builder used to configure and show the notification.</returns>
</member>
<member name="T:Artemis.UI.Shared.Services.Interfaces.IWindowService">
<summary>
A service that can be used to show windows and dialogs.
</summary>
</member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowWindow``1(System.ValueTuple{System.String,System.Object}[])">
<summary>
Creates a view model instance of type <typeparamref name="TViewModel" /> and shows its corresponding View as a window
Creates a view model instance of type <typeparamref name="TViewModel" /> and shows its corresponding View as a
window
</summary>
<typeparam name="TViewModel">The type of view model to create</typeparam>
<returns>The created view model</returns>
@ -1141,7 +1351,8 @@
</member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowDialogAsync``2(System.ValueTuple{System.String,System.Object}[])">
<summary>
Creates a view model instance of type <typeparamref name="TViewModel"/> and shows its corresponding View as a Dialog
Creates a view model instance of type <typeparamref name="TViewModel" /> and shows its corresponding View as a
Dialog
</summary>
<typeparam name="TViewModel">The view model type</typeparam>
<typeparam name="TResult">The return type</typeparam>
@ -1154,8 +1365,11 @@
<param name="title">The title of the dialog</param>
<param name="message">The message of the dialog</param>
<param name="confirm">The text of the confirm button</param>
<param name="cancel">The text of the cancel button, if <see langword="null"/> the cancel button will not be shown</param>
<returns>A task containing the result of the dialog, <see langword="true"/> if confirmed; otherwise <see langword="false"/></returns>
<param name="cancel">The text of the cancel button, if <see langword="null" /> the cancel button will not be shown</param>
<returns>
A task containing the result of the dialog, <see langword="true" /> if confirmed; otherwise
<see langword="false" />
</returns>
</member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.CreateOpenFileDialog">
<summary>
@ -1212,6 +1426,11 @@
Occurs when the main window has been closed
</summary>
</member>
<member name="T:Artemis.UI.Shared.Services.MainWindowService.IMainWindowService">
<summary>
A service that can be used to manage the state of the main window.
</summary>
</member>
<member name="P:Artemis.UI.Shared.Services.MainWindowService.IMainWindowService.IsMainWindowOpen">
<summary>
Gets a boolean indicating whether the main window is currently open

View File

@ -88,22 +88,26 @@ namespace Artemis.UI.Shared.Controls
/// <summary>
/// Gets or sets the currently displayed icon as either a <see cref="MaterialIconKind" /> or an <see cref="Uri" />
/// pointing
/// to an SVG
/// pointing to an SVG
/// </summary>
public static readonly StyledProperty<Hotkey?> HotkeyProperty =
AvaloniaProperty.Register<HotkeyBox, Hotkey?>(nameof(Hotkey), defaultBindingMode: BindingMode.TwoWay, notifying: HotkeyChanging);
/// <summary>
/// Gets or sets the watermark of the hotkey box when it is empty.
/// </summary>
public static readonly StyledProperty<string?> WatermarkProperty =
AvaloniaProperty.Register<HotkeyBox, string?>(nameof(Watermark));
/// <summary>
/// Gets or sets a boolean indicating whether the watermark should float above the hotkey box when it is not empty.
/// </summary>
public static readonly StyledProperty<bool> UseFloatingWatermarkProperty =
AvaloniaProperty.Register<HotkeyBox, bool>(nameof(UseFloatingWatermark));
/// <summary>
/// Gets or sets the currently displayed icon as either a <see cref="MaterialIconKind" /> or an <see cref="Uri" />
/// pointing
/// to an SVG
/// pointing to an SVG
/// </summary>
public Hotkey? Hotkey
{
@ -111,12 +115,18 @@ namespace Artemis.UI.Shared.Controls
set => SetValue(HotkeyProperty, value);
}
/// <summary>
/// Gets or sets the watermark of the hotkey box when it is empty.
/// </summary>
public string? Watermark
{
get => GetValue(WatermarkProperty);
set => SetValue(WatermarkProperty, value);
}
/// <summary>
/// Gets or sets a boolean indicating whether the watermark should float above the hotkey box when it is not empty.
/// </summary>
public bool UseFloatingWatermark
{
get => GetValue(UseFloatingWatermarkProperty);

View File

@ -13,7 +13,7 @@ namespace Artemis.UI.Shared.Converters
public class ColorToSKColorConverter : IValueConverter
{
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is Color avaloniaColor)
return new SKColor(avaloniaColor.R, avaloniaColor.G, avaloniaColor.B, avaloniaColor.A);
@ -24,7 +24,7 @@ namespace Artemis.UI.Shared.Converters
}
/// <inheritdoc />
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
Color result = new(0, 0, 0, 0);
if (value is SKColor skColor)

View File

@ -11,13 +11,13 @@ namespace Artemis.UI.Shared.Converters
public class EnumToBooleanConverter : IValueConverter
{
/// <inheritdoc />
public object Convert(object? value, Type targetType, object parameter, CultureInfo culture)
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return Equals(value, parameter);
}
/// <inheritdoc />
public object ConvertBack(object? value, Type targetType, object parameter, CultureInfo culture)
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return value?.Equals(true) == true ? parameter : BindingOperations.DoNothing;
}

View File

@ -13,7 +13,7 @@ namespace Artemis.UI.Shared.Converters
public class SKColorToColorConverter : IValueConverter
{
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
Color result = new(0, 0, 0, 0);
if (value is SKColor skColor)
@ -25,7 +25,7 @@ namespace Artemis.UI.Shared.Converters
}
/// <inheritdoc />
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is Color avaloniaColor)
return new SKColor(avaloniaColor.R, avaloniaColor.G, avaloniaColor.B, avaloniaColor.A);

View File

@ -21,7 +21,7 @@ namespace Artemis.UI.Shared.Converters
}
/// <inheritdoc />
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}

View File

@ -1,11 +1,16 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Shared.DefaultTypes.DataModel.Display
{
public partial class DefaultDataModelDisplayView : UserControl
/// <summary>
/// Represents a default data model display view.
/// </summary>
public class DefaultDataModelDisplayView : UserControl
{
/// <summary>
/// Creates a new instance of the <see cref="DefaultDataModelDisplayView" /> class.
/// </summary>
public DefaultDataModelDisplayView()
{
InitializeComponent();

View File

@ -22,6 +22,7 @@ namespace Artemis.UI.Shared.DefaultTypes.DataModel.Display
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
PreserveReferencesHandling = PreserveReferencesHandling.None
};
_display = "null";
}
public string Display

View File

@ -10,6 +10,9 @@ using ReactiveUI;
namespace Artemis.UI.Shared.Services.Builders
{
/// <summary>
/// Represents a builder that can be used to create Fluent UI dialogs.
/// </summary>
public class ContentDialogBuilder
{
private readonly ContentDialog _contentDialog;
@ -27,24 +30,44 @@ namespace Artemis.UI.Shared.Services.Builders
};
}
/// <summary>
/// Changes the title of the dialog.
/// </summary>
/// <param name="title">The new title.</param>
/// <returns>The builder that can be used to further build the dialog.</returns>
public ContentDialogBuilder WithTitle(string? title)
{
_contentDialog.Title = title;
return this;
}
/// <summary>
/// Changes the content of the dialog.
/// </summary>
/// <param name="content">The new content.</param>
/// <returns>The builder that can be used to further build the dialog.</returns>
public ContentDialogBuilder WithContent(string? content)
{
_contentDialog.Content = content;
return this;
}
/// <summary>
/// Changes the default button of the dialog that is pressed on enter.
/// </summary>
/// <param name="defaultButton">The default button.</param>
/// <returns>The builder that can be used to further build the dialog.</returns>
public ContentDialogBuilder WithDefaultButton(ContentDialogButton defaultButton)
{
_contentDialog.DefaultButton = defaultButton;
_contentDialog.DefaultButton = (FluentAvalonia.UI.Controls.ContentDialogButton) defaultButton;
return this;
}
/// <summary>
/// Changes the primary button of the dialog.
/// </summary>
/// <param name="configure">An action to configure the button.</param>
/// <returns>The builder that can be used to further build the dialog.</returns>
public ContentDialogBuilder HavingPrimaryButton(Action<ContentDialogButtonBuilder> configure)
{
ContentDialogButtonBuilder builder = new();
@ -65,6 +88,11 @@ namespace Artemis.UI.Shared.Services.Builders
return this;
}
/// <summary>
/// Changes the secondary button of the dialog.
/// </summary>
/// <param name="configure">An action to configure the button.</param>
/// <returns>The builder that can be used to further build the dialog.</returns>
public ContentDialogBuilder HavingSecondaryButton(Action<ContentDialogButtonBuilder> configure)
{
ContentDialogButtonBuilder builder = new();
@ -85,12 +113,24 @@ namespace Artemis.UI.Shared.Services.Builders
return this;
}
/// <summary>
/// Changes the text of the close button of the dialog.
/// </summary>
/// <param name="text">The new text.</param>
/// <returns>The builder that can be used to further build the dialog.</returns>
public ContentDialogBuilder WithCloseButtonText(string? text)
{
_contentDialog.CloseButtonText = text;
return this;
}
/// <summary>
/// Changes the view model of the content dialog, hosting it inside the dialog.
/// </summary>
/// <typeparam name="T">The type of the view model to host.</typeparam>
/// <param name="viewModel">The resulting view model.</param>
/// <param name="parameters">Optional parameters to pass to the constructor of the view model, case and order sensitive.</param>
/// <returns>The builder that can be used to further build the dialog.</returns>
public ContentDialogBuilder WithViewModel<T>(out T viewModel, params (string name, object? value)[] parameters) where T : ContentDialogViewModelBase
{
IParameter[] paramsArray = parameters.Select(kv => new ConstructorArgument(kv.name, kv.value)).Cast<IParameter>().ToArray();
@ -102,6 +142,11 @@ namespace Artemis.UI.Shared.Services.Builders
return this;
}
/// <summary>
/// Asynchronously shows the content dialog.
/// </summary>
/// <returns>A task containing the result of the content dialog.</returns>
/// <exception cref="ArtemisSharedUIException">Thrown when the parent window does not contain a panel at its root.</exception>
public async Task<ContentDialogResult> ShowAsync()
{
if (_parent.Content is not Panel panel)
@ -125,6 +170,35 @@ namespace Artemis.UI.Shared.Services.Builders
}
}
/// <summary>
/// Represents a content dialog button.
/// </summary>
public enum ContentDialogButton
{
/// <summary>
/// No button.
/// </summary>
None,
/// <summary>
/// The primary button.
/// </summary>
Primary,
/// <summary>
/// The secondary button.
/// </summary>
Secondary,
/// <summary>
/// The close button.
/// </summary>
Close,
}
/// <summary>
/// Represents a builder that can be used to create buttons inside content dialogs.
/// </summary>
public class ContentDialogButtonBuilder
{
internal ContentDialogButtonBuilder()
@ -133,20 +207,48 @@ namespace Artemis.UI.Shared.Services.Builders
internal string? Text { get; set; }
internal ICommand? Command { get; set; }
internal Action? Action { get; set; }
internal object? CommandParameter { get; set; }
/// <summary>
/// Changes text message of the button.
/// </summary>
/// <param name="text">The new text.</param>
/// <returns>The notification builder that can be used to further build the button.</returns>
public ContentDialogButtonBuilder WithText(string? text)
{
Text = text;
return this;
}
/// <summary>
/// Changes action that is called when the button is clicked.
/// </summary>
/// <param name="action">The action to call when the button is clicked.</param>
/// <returns>The builder that can be used to further build the button.</returns>
public ContentDialogButtonBuilder WithAction(Action action)
{
Action = action;
Command = ReactiveCommand.Create(() => Action());
return this;
}
/// <summary>
/// Changes command that is called when the button is clicked.
/// </summary>
/// <param name="command">The command to call when the button is clicked.</param>
/// <returns>The builder that can be used to further build the button.</returns>
public ContentDialogButtonBuilder WithCommand(ICommand? command)
{
Command = command;
return this;
}
/// <summary>
/// Changes parameter of the command that is called when the button is clicked.
/// </summary>
/// <param name="commandParameter">The parameter of the command to call when the button is clicked.</param>
/// <returns>The builder that can be used to further build the button.</returns>
public ContentDialogButtonBuilder WithCommandParameter(object? commandParameter)
{
CommandParameter = commandParameter;

View File

@ -101,7 +101,7 @@ namespace Artemis.UI.Shared.Services.Builders
}
/// <summary>
/// Changes the action button of the dialog.
/// Changes the action button of the notification.
/// </summary>
/// <param name="configure">An action to configure the button.</param>
/// <returns>The notification builder that can be used to further build the notification.</returns>
@ -154,6 +154,7 @@ namespace Artemis.UI.Shared.Services.Builders
private Action? _action;
private ICommand? _command;
private string _text = "Text";
private object? _commandParameter;
/// <summary>
/// Changes text message of the button.
@ -170,7 +171,7 @@ namespace Artemis.UI.Shared.Services.Builders
/// Changes action that is called when the button is clicked.
/// </summary>
/// <param name="action">The action to call when the button is clicked.</param>
/// <returns>The notification builder that can be used to further build the button.</returns>
/// <returns>The builder that can be used to further build the button.</returns>
public NotificationButtonBuilder WithAction(Action action)
{
_command = null;
@ -182,7 +183,7 @@ namespace Artemis.UI.Shared.Services.Builders
/// Changes command that is called when the button is clicked.
/// </summary>
/// <param name="command">The command to call when the button is clicked.</param>
/// <returns>The notification builder that can be used to further build the button.</returns>
/// <returns>The builder that can be used to further build the button.</returns>
public NotificationButtonBuilder WithCommand(ICommand command)
{
_action = null;
@ -190,21 +191,50 @@ namespace Artemis.UI.Shared.Services.Builders
return this;
}
/// <summary>
/// Changes parameter of the command that is called when the button is clicked.
/// </summary>
/// <param name="commandParameter">The parameter of the command to call when the button is clicked.</param>
/// <returns>The builder that can be used to further build the button.</returns>
public NotificationButtonBuilder WithCommandParameter(object? commandParameter)
{
_commandParameter = commandParameter;
return this;
}
internal IControl Build()
{
if (_action != null)
return new Button {Content = _text, Command = ReactiveCommand.Create(() => _action())};
if (_command != null)
return new Button {Content = _text, Command = _command};
return new Button {Content = _text, Command = _command, CommandParameter = _commandParameter};
return new Button {Content = _text};
}
}
/// <summary>
/// Represents a severity of a notification.
/// </summary>
public enum NotificationSeverity
{
/// <summary>
/// A severity for informational messages.
/// </summary>
Informational,
/// <summary>
/// A severity for success messages.
/// </summary>
Success,
/// <summary>
/// A severity for warning messages.
/// </summary>
Warning,
/// <summary>
/// A severity for error messages.
/// </summary>
Error
}
}

View File

@ -12,6 +12,10 @@ namespace Artemis.UI.Shared.Services.Builders
private readonly OpenFileDialog _openFileDialog;
private readonly Window _parent;
/// <summary>
/// Creates a new instance of the <see cref="OpenFileDialogBuilder"/> class.
/// </summary>
/// <param name="parent">The parent window that will host the dialog.</param>
public OpenFileDialogBuilder(Window parent)
{
_parent = parent;
@ -67,7 +71,7 @@ namespace Artemis.UI.Shared.Services.Builders
}
/// <summary>
/// Shows the file dialog
/// Asynchronously shows the file dialog.
/// </summary>
/// <returns>
/// A task that on completion returns an array containing the full path to the selected

View File

@ -12,6 +12,10 @@ namespace Artemis.UI.Shared.Services.Builders
private readonly Window _parent;
private readonly SaveFileDialog _saveFileDialog;
/// <summary>
/// Creates a new instance of the <see cref="SaveFileDialogBuilder" /> class.
/// </summary>
/// <param name="parent">The parent window that will host the notification.</param>
public SaveFileDialogBuilder(Window parent)
{
_parent = parent;
@ -67,7 +71,7 @@ namespace Artemis.UI.Shared.Services.Builders
}
/// <summary>
/// Shows the save file dialog.
/// Asynchronously shows the save file dialog.
/// </summary>
/// <returns>
/// A task that on completion contains the full path of the save location, or null if the

View File

@ -2,8 +2,15 @@
namespace Artemis.UI.Shared.Services.Interfaces
{
/// <summary>
/// A service that can be used to create notifications in either the application or on the desktop.
/// </summary>
public interface INotificationService : IArtemisSharedUIService
{
/// <summary>
/// Creates an in-app notification using a builder.
/// </summary>
/// <returns>A builder used to configure and show the notification.</returns>
NotificationBuilder CreateNotification();
}
}

View File

@ -5,10 +5,14 @@ using Avalonia.Controls;
namespace Artemis.UI.Shared.Services.Interfaces
{
/// <summary>
/// A service that can be used to show windows and dialogs.
/// </summary>
public interface IWindowService : IArtemisSharedUIService
{
/// <summary>
/// Creates a view model instance of type <typeparamref name="TViewModel" /> and shows its corresponding View as a window
/// Creates a view model instance of type <typeparamref name="TViewModel" /> and shows its corresponding View as a
/// window
/// </summary>
/// <typeparam name="TViewModel">The type of view model to create</typeparam>
/// <returns>The created view model</returns>
@ -36,7 +40,8 @@ namespace Artemis.UI.Shared.Services.Interfaces
Task<TResult> ShowDialogAsync<TResult>(DialogViewModelBase<TResult> viewModel);
/// <summary>
/// Creates a view model instance of type <typeparamref name="TViewModel"/> and shows its corresponding View as a Dialog
/// Creates a view model instance of type <typeparamref name="TViewModel" /> and shows its corresponding View as a
/// Dialog
/// </summary>
/// <typeparam name="TViewModel">The view model type</typeparam>
/// <typeparam name="TResult">The return type</typeparam>
@ -49,8 +54,11 @@ namespace Artemis.UI.Shared.Services.Interfaces
/// <param name="title">The title of the dialog</param>
/// <param name="message">The message of the dialog</param>
/// <param name="confirm">The text of the confirm button</param>
/// <param name="cancel">The text of the cancel button, if <see langword="null"/> the cancel button will not be shown</param>
/// <returns>A task containing the result of the dialog, <see langword="true"/> if confirmed; otherwise <see langword="false"/></returns>
/// <param name="cancel">The text of the cancel button, if <see langword="null" /> the cancel button will not be shown</param>
/// <returns>
/// A task containing the result of the dialog, <see langword="true" /> if confirmed; otherwise
/// <see langword="false" />
/// </returns>
Task<bool> ShowConfirmContentDialog(string title, string message, string confirm = "Confirm", string? cancel = "Cancel");
/// <summary>
@ -75,6 +83,6 @@ namespace Artemis.UI.Shared.Services.Interfaces
/// Gets the current window of the application
/// </summary>
/// <returns>The current window of the application</returns>
Window GetCurrentWindow();
Window? GetCurrentWindow();
}
}

View File

@ -3,6 +3,9 @@ using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Shared.Services.MainWindowService
{
/// <summary>
/// A service that can be used to manage the state of the main window.
/// </summary>
public interface IMainWindowService : IArtemisSharedUIService
{
/// <summary>

View File

@ -1,9 +1,10 @@
using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.Interfaces;
using Avalonia.Controls;
namespace Artemis.UI.Shared.Services
{
public class NotificationService : INotificationService
internal class NotificationService : INotificationService
{
private readonly IWindowService _windowService;
@ -14,7 +15,11 @@ namespace Artemis.UI.Shared.Services
public NotificationBuilder CreateNotification()
{
return new NotificationBuilder(_windowService.GetCurrentWindow());
Window? currentWindow = _windowService.GetCurrentWindow();
if (currentWindow == null)
throw new ArtemisSharedUIException("Can't show an in-app notification without any windows being shown.");
return new NotificationBuilder(currentWindow);
}
}
}

View File

@ -24,6 +24,9 @@ namespace Artemis.UI.Shared.Services
public async Task CopyException()
{
if (Application.Current?.Clipboard == null)
return;
await Application.Current.Clipboard.SetTextAsync(Exception.ToString());
_notificationService.CreateNotification()
.WithMessage("Copied stack trace to clipboard.")

View File

@ -39,14 +39,10 @@ namespace Artemis.UI.Shared.Services
Type? type = viewModel.GetType().Assembly.GetType(name);
if (type == null)
{
throw new ArtemisSharedUIException($"Failed to find a window named {name}.");
}
if (!type.IsAssignableTo(typeof(Window)))
{
throw new ArtemisSharedUIException($"Type {name} is not a window.");
}
Window window = (Window) Activator.CreateInstance(type)!;
window.DataContext = viewModel;
@ -77,20 +73,16 @@ namespace Artemis.UI.Shared.Services
public async Task<TResult> ShowDialogAsync<TResult>(DialogViewModelBase<TResult> viewModel)
{
Window parent = GetCurrentWindow();
Window? parent = GetCurrentWindow();
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
Type? type = viewModel.GetType().Assembly.GetType(name);
if (type == null)
{
throw new ArtemisSharedUIException($"Failed to find a window named {name}.");
}
if (!type.IsAssignableTo(typeof(Window)))
{
throw new ArtemisSharedUIException($"Type {name} is not a window.");
}
Window window = (Window) Activator.CreateInstance(type)!;
window.DataContext = viewModel;
@ -122,25 +114,32 @@ namespace Artemis.UI.Shared.Services
public ContentDialogBuilder CreateContentDialog()
{
return new ContentDialogBuilder(_kernel, GetCurrentWindow());
Window? currentWindow = GetCurrentWindow();
if (currentWindow == null)
throw new ArtemisSharedUIException("Can't show a content dialog without any windows being shown.");
return new ContentDialogBuilder(_kernel, currentWindow);
}
public OpenFileDialogBuilder CreateOpenFileDialog()
{
return new OpenFileDialogBuilder(GetCurrentWindow());
Window? currentWindow = GetCurrentWindow();
if (currentWindow == null)
throw new ArtemisSharedUIException("Can't show an open file dialog without any windows being shown.");
return new OpenFileDialogBuilder(currentWindow);
}
public SaveFileDialogBuilder CreateSaveFileDialog()
{
return new SaveFileDialogBuilder(GetCurrentWindow());
Window? currentWindow = GetCurrentWindow();
if (currentWindow == null)
throw new ArtemisSharedUIException("Can't show a save file dialog without any windows being shown.");
return new SaveFileDialogBuilder(currentWindow);
}
public Window? GetCurrentWindow()
{
if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime classic)
{
throw new ArtemisSharedUIException("Can't show a dialog when application lifetime is not IClassicDesktopStyleApplicationLifetime.");
}
if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime classic)
throw new ArtemisSharedUIException("Find an open window when application lifetime is not IClassicDesktopStyleApplicationLifetime.");
Window? parent = classic.Windows.FirstOrDefault(w => w.IsActive && w.ShowInTaskbar) ?? classic.MainWindow;
return parent;

View File

@ -34,7 +34,7 @@ namespace Artemis.UI.Windows
Core.Utilities.RestartRequested += UtilitiesOnRestartRequested;
// On Windows shutdown dispose the kernel just so device providers get a chance to clean up
if (Application.Current.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
if (Application.Current?.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
{
controlledApplicationLifetime.Exit += (_, _) =>
{
@ -159,7 +159,7 @@ namespace Artemis.UI.Windows
}
// Lets try a graceful shutdown, PowerShell will kill if needed
if (Application.Current.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
if (Application.Current?.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
Dispatcher.UIThread.Post(() => controlledApplicationLifetime.Shutdown());
}
@ -168,7 +168,7 @@ namespace Artemis.UI.Windows
// Use PowerShell to kill the process after 8 sec just in case
RunForcedShutdownIfEnabled();
if (Application.Current.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
if (Application.Current?.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
Dispatcher.UIThread.Post(() => controlledApplicationLifetime.Shutdown());
}

View File

@ -3,6 +3,7 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />

View File

@ -113,13 +113,13 @@ namespace Artemis.UI.Windows.Providers.Input
if (key == KeyboardKey.LeftCtrl && keyboardData.Keyboard.ScanCode == 56)
return;
string identifier = data.Device?.DevicePath;
string? identifier = data.Device?.DevicePath;
// Let the core know there is an identifier so it can store new identifications if applicable
if (identifier != null)
OnIdentifierReceived(identifier, InputDeviceType.Keyboard);
ArtemisDevice device = null;
ArtemisDevice? device = null;
if (identifier != null)
try
{
@ -180,9 +180,10 @@ namespace Artemis.UI.Windows.Providers.Input
return;
}
ArtemisDevice device = null;
string identifier = data.Device?.DevicePath;
ArtemisDevice? device = null;
string? identifier = data.Device?.DevicePath;
if (identifier != null)
{
try
{
device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Mouse);
@ -191,6 +192,7 @@ namespace Artemis.UI.Windows.Providers.Input
{
_logger.Warning(e, "Failed to retrieve input device by its identifier");
}
}
// Debug.WriteLine($"Buttons: {mouseData.Mouse.Buttons}, Data: {mouseData.Mouse.ButtonData}, Flags: {mouseData.Mouse.Flags}, XY: {mouseData.Mouse.LastX},{mouseData.Mouse.LastY}");

View File

@ -91,7 +91,7 @@ namespace Artemis.UI.Windows.Utilities
}
PROCESS_INFORMATION pi = new();
if (!CreateProcessWithTokenW(hPrimaryToken, 0, fileName, $"\"{fileName}\" {arguments}", 0, IntPtr.Zero, Path.GetDirectoryName(fileName), ref si, out pi))
if (!CreateProcessWithTokenW(hPrimaryToken, 0, fileName, $"\"{fileName}\" {arguments}", 0, IntPtr.Zero, Path.GetDirectoryName(fileName)!, ref si, out pi))
{
// Get the last error and display it.
int error = Marshal.GetLastWin32Error();
@ -203,7 +203,7 @@ namespace Artemis.UI.Windows.Utilities
private static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LookupPrivilegeValue(string host, string name, ref LUID pluid);
private static extern bool LookupPrivilegeValue(string? host, string name, ref LUID pluid);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TOKEN_PRIVILEGES newst, int len, IntPtr prev, IntPtr relen);

View File

@ -12,7 +12,7 @@ namespace Artemis.UI.Converters
public class ColorToSolidColorBrushConverter : IValueConverter
{
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return new SolidColorBrush(!(value is RGBColor color)
? new Color(0, 0, 0, 0)
@ -20,7 +20,7 @@ namespace Artemis.UI.Converters
}
/// <inheritdoc />
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return !(value is SolidColorBrush brush)
? RGBColor.Transparent

View File

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using Avalonia.Data.Converters;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Converters
{
public class EnumToCollectionConverter : MarkupExtension, IValueConverter
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
private static string Description(Enum value)
{
object[] attributes = value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Any())
return (attributes.First() as DescriptionAttribute)?.Description;
// If no description is found, the least we can do is replace underscores with spaces
TextInfo ti = CultureInfo.CurrentCulture.TextInfo;
return ti.ToTitleCase(ti.ToLower(value.ToString().Replace("_", " ")));
}
private static IEnumerable<Tuple<object, object>> GetAllValuesAndDescriptions(Type t)
{
if (!t.IsEnum)
throw new ArgumentException($"{nameof(t)} must be an enum type");
return Enum.GetValues(t).Cast<Enum>().Select(e => new Tuple<object, object>(e, Description(e))).ToList();
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return GetAllValuesAndDescriptions(value.GetType());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@ -10,15 +10,15 @@ namespace Artemis.UI.Converters
#region Implementation of IValueConverter
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return value?.ToString();
}
/// <inheritdoc />
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (Enum.TryParse(typeof(LedId), value?.ToString(), true, out object parsedLedId))
if (Enum.TryParse(typeof(LedId), value?.ToString(), true, out object? parsedLedId))
return parsedLedId;
return LedId.Unknown1;
}

View File

@ -8,7 +8,7 @@ namespace Artemis.UI.Converters
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is double number)
return number * 100.0;
@ -16,7 +16,7 @@ namespace Artemis.UI.Converters
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is double number)
return number / 100.0;

View File

@ -7,14 +7,14 @@ namespace Artemis.UI.Converters
{
public class UriToFileNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is Uri uri && uri.IsFile)
return Path.GetFileName(uri.LocalPath);
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return value;
}

View File

@ -9,8 +9,10 @@ namespace Artemis.UI.Converters
public class ValuesAdditionConverter : IMultiValueConverter
{
/// <inheritdoc />
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
public object Convert(IList<object?>? values, Type targetType, object? parameter, CultureInfo culture)
{
if (values == null)
return 0.0;
return values.Where(v => v is double).Cast<double>().Sum();
}
}

View File

@ -16,7 +16,7 @@ namespace Artemis.UI.Screens.Debugger.Render
private Bitmap? _currentFrame;
private string? _frameTargetPath;
private string _renderer;
private string? _renderer;
private int _renderHeight;
private int _renderWidth;
@ -56,7 +56,7 @@ namespace Artemis.UI.Screens.Debugger.Render
set => this.RaiseAndSetIfChanged(ref _renderHeight, value);
}
public string Renderer
public string? Renderer
{
get => _renderer;
set => this.RaiseAndSetIfChanged(ref _renderer, value);

View File

@ -28,6 +28,9 @@ namespace Artemis.UI.Screens.Device
public async Task CopyToClipboard(string content)
{
if (Application.Current?.Clipboard == null)
return;
await Application.Current.Clipboard.SetTextAsync(content);
_notificationService.CreateNotification().WithMessage("Copied path to clipboard.").Show();
}

View File

@ -16,7 +16,7 @@ namespace Artemis.UI.Screens.Device
private readonly IRgbService _rgbService;
private readonly IInputService _inputService;
private readonly ObservableCollection<ArtemisLed> _selectedLeds;
private ArtemisLed _selectedLed;
private ArtemisLed? _selectedLed;
public InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds, IRgbService rgbService, IInputService inputService)
{
@ -34,7 +34,7 @@ namespace Artemis.UI.Screens.Device
public ArtemisDevice Device { get; }
public ArtemisLed SelectedLed
public ArtemisLed? SelectedLed
{
get => _selectedLed;
set => this.RaiseAndSetIfChanged(ref _selectedLed, value);
@ -57,7 +57,7 @@ namespace Artemis.UI.Screens.Device
bool foundLedId = InputKeyUtilities.KeyboardKeyLedIdMap.TryGetValue(e.Key, out LedId ledId);
if (!foundLedId)
return;
ArtemisLed artemisLed = Device.GetLed(ledId, false);
ArtemisLed? artemisLed = Device.GetLed(ledId, false);
if (artemisLed == null)
return;

View File

@ -53,7 +53,7 @@ namespace Artemis.UI.Screens.Root
_assetLoader = assetLoader;
_defaultTitleBarViewModel = defaultTitleBarViewModel;
_sidebarVmFactory = sidebarVmFactory;
_lifeTime = (IClassicDesktopStyleApplicationLifetime) Application.Current.ApplicationLifetime;
_lifeTime = (IClassicDesktopStyleApplicationLifetime) Application.Current!.ApplicationLifetime!;
coreService.StartupArguments = _lifeTime.Args.ToList();
mainWindowService.ConfigureMainWindowProvider(this);
@ -127,15 +127,15 @@ namespace Artemis.UI.Screens.Root
Icon = new WindowIcon(_assetLoader.Open(new Uri("avares://Artemis.UI/Assets/Images/Logo/bow.ico"))),
Command = ReactiveCommand.Create(OpenMainWindow)
};
_trayIcon.Menu = (NativeMenu?) Application.Current.FindResource("TrayIconMenu");
_trayIcon.Menu = (NativeMenu?) Application.Current!.FindResource("TrayIconMenu");
_trayIcons = new TrayIcons {_trayIcon};
TrayIcon.SetIcons(Application.Current, _trayIcons);
TrayIcon.SetIcons(Application.Current!, _trayIcons);
}
private void HideTrayIcon()
{
_trayIcon?.Dispose();
TrayIcon.SetIcons(Application.Current, null!);
TrayIcon.SetIcons(Application.Current!, null!);
_trayIcon = null;
_trayIcons = null;

View File

@ -69,7 +69,7 @@ namespace Artemis.UI.Screens.Settings
SearchPluginInput = plugin.Info.Name;
// Enable it via the VM to enable the prerequisite dialog
PluginSettingsViewModel pluginViewModel = Plugins.FirstOrDefault(i => i.Plugin == plugin);
PluginSettingsViewModel? pluginViewModel = Plugins.FirstOrDefault(i => i.Plugin == plugin);
if (pluginViewModel is {IsEnabled: false})
pluginViewModel.IsEnabled = true;

View File

@ -22,18 +22,18 @@ namespace Artemis.UI.Screens.Sidebar
private readonly ProfileCategory _profileCategory;
private readonly IProfileService _profileService;
private readonly IWindowService _windowService;
private ProfileConfigurationIconType _iconType;
private Hotkey? _disableHotkey;
private Hotkey? _enableHotkey;
private ProfileConfigurationHotkeyMode _hotkeyMode;
private ProfileConfigurationIconType _iconType;
private ObservableCollection<ProfileIconViewModel>? _materialIcons;
private ProfileConfiguration _profileConfiguration;
private string _profileName;
private Bitmap? _selectedBitmapSource;
private string? _selectedIconPath;
private ProfileIconViewModel? _selectedMaterialIcon;
private ProfileModuleViewModel? _selectedModule;
private string? _selectedIconPath;
private SvgImage? _selectedSvgSource;
private Hotkey? _enableHotkey;
private Hotkey? _disableHotkey;
public ProfileConfigurationEditViewModel(ProfileCategory profileCategory, ProfileConfiguration? profileConfiguration, IWindowService windowService,
IProfileService profileService, IPluginManagementService pluginManagementService)
@ -46,9 +46,9 @@ namespace Artemis.UI.Screens.Sidebar
_iconType = _profileConfiguration.Icon.IconType;
_hotkeyMode = _profileConfiguration.HotkeyMode;
if (_profileConfiguration.EnableHotkey != null)
_enableHotkey = new Hotkey() {Key = _profileConfiguration.EnableHotkey.Key, Modifiers = profileConfiguration.EnableHotkey.Modifiers};
_enableHotkey = new Hotkey {Key = _profileConfiguration.EnableHotkey.Key, Modifiers = _profileConfiguration.EnableHotkey.Modifiers};
if (_profileConfiguration.DisableHotkey != null)
_disableHotkey = new Hotkey() {Key = _profileConfiguration.DisableHotkey.Key, Modifiers = profileConfiguration.DisableHotkey.Modifiers};
_disableHotkey = new Hotkey {Key = _profileConfiguration.DisableHotkey.Key, Modifiers = _profileConfiguration.DisableHotkey.Modifiers};
IsNew = profileConfiguration == null;
DisplayName = IsNew ? "Artemis | Add profile" : "Artemis | Edit profile";
@ -209,11 +209,15 @@ namespace Artemis.UI.Screens.Sidebar
SelectedBitmapSource = new Bitmap(_profileConfiguration.Icon.GetIconStream());
}
else if (_profileConfiguration.Icon.IconType == ProfileConfigurationIconType.SvgImage)
{
Stream? iconStream = _profileConfiguration.Icon.GetIconStream();
if (iconStream != null)
{
SvgSource newSource = new();
newSource.Load(_profileConfiguration.Icon.GetIconStream());
newSource.Load(iconStream);
SelectedSvgSource = new SvgImage {Source = newSource};
}
}
// Prepare the contents of the dropdown box, it should be virtualized so no need to wait with this
ObservableCollection<ProfileIconViewModel> icons = new(Enum.GetValues<MaterialIconKind>()
@ -231,7 +235,9 @@ namespace Artemis.UI.Screens.Sidebar
private async Task SaveIcon()
{
if (IconType == ProfileConfigurationIconType.MaterialIcon && SelectedMaterialIcon != null)
{
ProfileConfiguration.Icon.SetIconByName(SelectedMaterialIcon.Icon.ToString());
}
else if (_selectedIconPath != null)
{
await using FileStream fileStream = File.OpenRead(_selectedIconPath);

View File

@ -6,23 +6,24 @@ using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Services;
using Artemis.UI.Services.ProfileEditor;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.Interfaces;
using FluentAvalonia.UI.Controls;
using ReactiveUI;
namespace Artemis.UI.Screens.Sidebar
{
public class SidebarCategoryViewModel : ActivatableViewModelBase
{
private readonly SidebarViewModel _sidebarViewModel;
private readonly IProfileService _profileService;
private readonly IWindowService _windowService;
private readonly SidebarViewModel _sidebarViewModel;
private readonly ISidebarVmFactory _vmFactory;
private readonly IWindowService _windowService;
private SidebarProfileConfigurationViewModel? _selectedProfileConfiguration;
public SidebarCategoryViewModel(SidebarViewModel sidebarViewModel, ProfileCategory profileCategory, IProfileService profileService, IWindowService windowService, IProfileEditorService profileEditorService, ISidebarVmFactory vmFactory)
public SidebarCategoryViewModel(SidebarViewModel sidebarViewModel, ProfileCategory profileCategory, IProfileService profileService, IWindowService windowService,
IProfileEditorService profileEditorService, ISidebarVmFactory vmFactory)
{
_sidebarViewModel = sidebarViewModel;
_profileService = profileService;
@ -86,7 +87,7 @@ namespace Artemis.UI.Screens.Sidebar
{
await _windowService.CreateContentDialog()
.WithTitle("Edit category")
.WithViewModel<SidebarCategoryEditViewModel>(out var vm, ("category", ProfileCategory))
.WithViewModel(out SidebarCategoryEditViewModel vm, ("category", ProfileCategory))
.HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Confirm))
.HavingSecondaryButton(b => b.WithText("Delete").WithCommand(vm.Delete))
.WithCloseButtonText("Cancel")

View File

@ -2,7 +2,6 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
@ -12,11 +11,10 @@ using Artemis.UI.Screens.ProfileEditor;
using Artemis.UI.Screens.Settings;
using Artemis.UI.Screens.SurfaceEditor;
using Artemis.UI.Screens.Workshop;
using Artemis.UI.Services;
using Artemis.UI.Services.ProfileEditor;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.Interfaces;
using FluentAvalonia.UI.Controls;
using Material.Icons;
using Ninject;
using ReactiveUI;
@ -27,11 +25,11 @@ namespace Artemis.UI.Screens.Sidebar
public class SidebarViewModel : ActivatableViewModelBase
{
private readonly IScreen _hostScreen;
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileService _profileService;
private readonly IRgbService _rgbService;
private readonly ISidebarVmFactory _sidebarVmFactory;
private readonly IWindowService _windowService;
private readonly IProfileEditorService _profileEditorService;
private ArtemisDevice? _headerDevice;
private SidebarScreenViewModel? _selectedSidebarScreen;
@ -111,7 +109,7 @@ namespace Artemis.UI.Screens.Sidebar
{
await _windowService.CreateContentDialog()
.WithTitle("Add new category")
.WithViewModel<SidebarCategoryEditViewModel>(out var vm, ("category", null))
.WithViewModel(out SidebarCategoryEditViewModel vm, ("category", null))
.HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Confirm))
.WithCloseButtonText("Cancel")
.WithDefaultButton(ContentDialogButton.Primary)

View File

@ -35,6 +35,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
_settingsService = settingsService;
_deviceVmFactory = deviceVmFactory;
_windowService = windowService;
_cursor = Cursor.Default;
Device = device;