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"> <member name="F:Artemis.UI.Shared.Controls.HotkeyBox.HotkeyProperty">
<summary> <summary>
Gets or sets the currently displayed icon as either a <see cref="T:Material.Icons.MaterialIconKind" /> or an <see cref="T:System.Uri" /> Gets or sets the currently displayed icon as either a <see cref="T:Material.Icons.MaterialIconKind" /> or an <see cref="T:System.Uri" />
pointing pointing to an SVG
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> </summary>
</member> </member>
<member name="P:Artemis.UI.Shared.Controls.HotkeyBox.Hotkey"> <member name="P:Artemis.UI.Shared.Controls.HotkeyBox.Hotkey">
<summary> <summary>
Gets or sets the currently displayed icon as either a <see cref="T:Material.Icons.MaterialIconKind" /> or an <see cref="T:System.Uri" /> Gets or sets the currently displayed icon as either a <see cref="T:Material.Icons.MaterialIconKind" /> or an <see cref="T:System.Uri" />
pointing pointing to an SVG
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> </summary>
</member> </member>
<member name="M:Artemis.UI.Shared.Controls.NoInputTextBox.OnKeyDown(Avalonia.Input.KeyEventArgs)"> <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"> <member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelVisualizationViewModel.Dispose">
<inheritdoc /> <inheritdoc />
</member> </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"> <member name="T:Artemis.UI.Shared.DefaultTypes.DataModel.Display.DefaultDataModelDisplayViewModel">
<summary> <summary>
Represents the default data model display view model that is used when no display viewmodel specific for the type 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 Occurs when the the window hosting the view model should close
</summary> </summary>
</member> </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"> <member name="T:Artemis.UI.Shared.Services.Builders.FileDialogFilterBuilder">
<summary> <summary>
Represents a builder that can create a <see cref="T:Avalonia.Controls.FileDialogFilter" />. Represents a builder that can create a <see cref="T:Avalonia.Controls.FileDialogFilter" />.
@ -894,7 +1043,7 @@
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Builders.NotificationBuilder.HavingButton(System.Action{Artemis.UI.Shared.Services.Builders.NotificationButtonBuilder})"> <member name="M:Artemis.UI.Shared.Services.Builders.NotificationBuilder.HavingButton(System.Action{Artemis.UI.Shared.Services.Builders.NotificationButtonBuilder})">
<summary> <summary>
Changes the action button of the dialog. Changes the action button of the notification.
</summary> </summary>
<param name="configure">An action to configure the button.</param> <param name="configure">An action to configure the button.</param>
<returns>The notification builder that can be used to further build the notification.</returns> <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. Changes action that is called when the button is clicked.
</summary> </summary>
<param name="action">The action to call when the button is clicked.</param> <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>
<member name="M:Artemis.UI.Shared.Services.Builders.NotificationButtonBuilder.WithCommand(System.Windows.Input.ICommand)"> <member name="M:Artemis.UI.Shared.Services.Builders.NotificationButtonBuilder.WithCommand(System.Windows.Input.ICommand)">
<summary> <summary>
Changes command that is called when the button is clicked. Changes command that is called when the button is clicked.
</summary> </summary>
<param name="command">The command to call when the button is clicked.</param> <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>
<member name="T:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder"> <member name="T:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder">
<summary> <summary>
Represents a builder that can create a <see cref="T:Avalonia.Controls.OpenFileDialog" />. Represents a builder that can create a <see cref="T:Avalonia.Controls.OpenFileDialog" />.
</summary> </summary>
</member> </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"> <member name="M:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder.WithAllowMultiple">
<summary> <summary>
Indicate that the user can select multiple files. Indicate that the user can select multiple files.
@ -962,7 +1149,7 @@
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder.ShowAsync"> <member name="M:Artemis.UI.Shared.Services.Builders.OpenFileDialogBuilder.ShowAsync">
<summary> <summary>
Shows the file dialog Asynchronously shows the file dialog.
</summary> </summary>
<returns> <returns>
A task that on completion returns an array containing the full path to the selected 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" />. Represents a builder that can create a <see cref="T:Avalonia.Controls.SaveFileDialog" />.
</summary> </summary>
</member> </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)"> <member name="M:Artemis.UI.Shared.Services.Builders.SaveFileDialogBuilder.WithTitle(System.String)">
<summary> <summary>
Set the title of the dialog Set the title of the dialog
@ -1001,7 +1194,7 @@
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Builders.SaveFileDialogBuilder.ShowAsync"> <member name="M:Artemis.UI.Shared.Services.Builders.SaveFileDialogBuilder.ShowAsync">
<summary> <summary>
Shows the save file dialog. Asynchronously shows the save file dialog.
</summary> </summary>
<returns> <returns>
A task that on completion contains the full path of the save location, or null if the A task that on completion contains the full path of the save location, or null if the
@ -1111,29 +1304,46 @@
<param name="updateCallback">A function to call whenever the input was updated (submitted or not)</param> <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> <returns>The most appropriate input view model for the provided <paramref name="propertyType" /></returns>
</member> </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}[])"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowWindow``1(System.ValueTuple{System.String,System.Object}[])">
<summary> <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> </summary>
<typeparam name="TViewModel">The type of view model to create</typeparam> <typeparam name="TViewModel">The type of view model to create</typeparam>
<returns>The created view model</returns> <returns>The created view model</returns>
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowWindow(System.Object)"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowWindow(System.Object)">
<summary> <summary>
Given a ViewModel, show its corresponding View as a window Given a ViewModel, show its corresponding View as a window
</summary> </summary>
<param name="viewModel">ViewModel to show the View for</param> <param name="viewModel">ViewModel to show the View for</param>
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowExceptionDialog(System.String,System.Exception)"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowExceptionDialog(System.String,System.Exception)">
<summary> <summary>
Shows a dialog displaying the given exception Shows a dialog displaying the given exception
</summary> </summary>
<param name="title">The title of the dialog</param> <param name="title">The title of the dialog</param>
<param name="exception">The exception to display</param> <param name="exception">The exception to display</param>
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowDialogAsync``1(Artemis.UI.Shared.DialogViewModelBase{``0})"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowDialogAsync``1(Artemis.UI.Shared.DialogViewModelBase{``0})">
<summary> <summary>
Given an existing ViewModel, show its corresponding View as a Dialog Given an existing ViewModel, show its corresponding View as a Dialog
</summary> </summary>
<typeparam name="TResult">The return type</typeparam> <typeparam name="TResult">The return type</typeparam>
<param name="viewModel">ViewModel to show the View for</param> <param name="viewModel">ViewModel to show the View for</param>
@ -1141,7 +1351,8 @@
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowDialogAsync``2(System.ValueTuple{System.String,System.Object}[])"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowDialogAsync``2(System.ValueTuple{System.String,System.Object}[])">
<summary> <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> </summary>
<typeparam name="TViewModel">The view model type</typeparam> <typeparam name="TViewModel">The view model type</typeparam>
<typeparam name="TResult">The return type</typeparam> <typeparam name="TResult">The return type</typeparam>
@ -1149,35 +1360,38 @@
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowConfirmContentDialog(System.String,System.String,System.String,System.String)"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.ShowConfirmContentDialog(System.String,System.String,System.String,System.String)">
<summary> <summary>
Shows a content dialog asking the user to confirm an action Shows a content dialog asking the user to confirm an action
</summary> </summary>
<param name="title">The title of the dialog</param> <param name="title">The title of the dialog</param>
<param name="message">The message 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="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> <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> <returns>
A task containing the result of the dialog, <see langword="true" /> if confirmed; otherwise
<see langword="false" />
</returns>
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.CreateOpenFileDialog"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.CreateOpenFileDialog">
<summary> <summary>
Creates an open file dialog, use the fluent API to configure it Creates an open file dialog, use the fluent API to configure it
</summary> </summary>
<returns>The builder that can be used to configure the dialog</returns> <returns>The builder that can be used to configure the dialog</returns>
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.CreateSaveFileDialog"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.CreateSaveFileDialog">
<summary> <summary>
Creates a save file dialog, use the fluent API to configure it Creates a save file dialog, use the fluent API to configure it
</summary> </summary>
<returns>The builder that can be used to configure the dialog</returns> <returns>The builder that can be used to configure the dialog</returns>
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.CreateContentDialog"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.CreateContentDialog">
<summary> <summary>
Creates a content dialog, use the fluent API to configure it Creates a content dialog, use the fluent API to configure it
</summary> </summary>
<returns>The builder that can be used to configure the dialog</returns> <returns>The builder that can be used to configure the dialog</returns>
</member> </member>
<member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.GetCurrentWindow"> <member name="M:Artemis.UI.Shared.Services.Interfaces.IWindowService.GetCurrentWindow">
<summary> <summary>
Gets the current window of the application Gets the current window of the application
</summary> </summary>
<returns>The current window of the application</returns> <returns>The current window of the application</returns>
</member> </member>
@ -1212,6 +1426,11 @@
Occurs when the main window has been closed Occurs when the main window has been closed
</summary> </summary>
</member> </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"> <member name="P:Artemis.UI.Shared.Services.MainWindowService.IMainWindowService.IsMainWindowOpen">
<summary> <summary>
Gets a boolean indicating whether the main window is currently open Gets a boolean indicating whether the main window is currently open

View File

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

View File

@ -13,7 +13,7 @@ namespace Artemis.UI.Shared.Converters
public class ColorToSKColorConverter : IValueConverter public class ColorToSKColorConverter : IValueConverter
{ {
/// <inheritdoc /> /// <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) if (value is Color avaloniaColor)
return new SKColor(avaloniaColor.R, avaloniaColor.G, avaloniaColor.B, avaloniaColor.A); return new SKColor(avaloniaColor.R, avaloniaColor.G, avaloniaColor.B, avaloniaColor.A);
@ -24,7 +24,7 @@ namespace Artemis.UI.Shared.Converters
} }
/// <inheritdoc /> /// <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); Color result = new(0, 0, 0, 0);
if (value is SKColor skColor) if (value is SKColor skColor)

View File

@ -11,13 +11,13 @@ namespace Artemis.UI.Shared.Converters
public class EnumToBooleanConverter : IValueConverter public class EnumToBooleanConverter : IValueConverter
{ {
/// <inheritdoc /> /// <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); return Equals(value, parameter);
} }
/// <inheritdoc /> /// <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; return value?.Equals(true) == true ? parameter : BindingOperations.DoNothing;
} }

View File

@ -13,7 +13,7 @@ namespace Artemis.UI.Shared.Converters
public class SKColorToColorConverter : IValueConverter public class SKColorToColorConverter : IValueConverter
{ {
/// <inheritdoc /> /// <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); Color result = new(0, 0, 0, 0);
if (value is SKColor skColor) if (value is SKColor skColor)
@ -25,7 +25,7 @@ namespace Artemis.UI.Shared.Converters
} }
/// <inheritdoc /> /// <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) if (value is Color avaloniaColor)
return new SKColor(avaloniaColor.R, avaloniaColor.G, avaloniaColor.B, avaloniaColor.A); return new SKColor(avaloniaColor.R, avaloniaColor.G, avaloniaColor.B, avaloniaColor.A);

View File

@ -21,7 +21,7 @@ namespace Artemis.UI.Shared.Converters
} }
/// <inheritdoc /> /// <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(); throw new NotImplementedException();
} }

View File

@ -1,11 +1,16 @@
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
namespace Artemis.UI.Shared.DefaultTypes.DataModel.Display 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() public DefaultDataModelDisplayView()
{ {
InitializeComponent(); InitializeComponent();
@ -16,4 +21,4 @@ namespace Artemis.UI.Shared.DefaultTypes.DataModel.Display
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
} }
} }

View File

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

View File

@ -10,6 +10,9 @@ using ReactiveUI;
namespace Artemis.UI.Shared.Services.Builders namespace Artemis.UI.Shared.Services.Builders
{ {
/// <summary>
/// Represents a builder that can be used to create Fluent UI dialogs.
/// </summary>
public class ContentDialogBuilder public class ContentDialogBuilder
{ {
private readonly ContentDialog _contentDialog; 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) public ContentDialogBuilder WithTitle(string? title)
{ {
_contentDialog.Title = title; _contentDialog.Title = title;
return this; 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) public ContentDialogBuilder WithContent(string? content)
{ {
_contentDialog.Content = content; _contentDialog.Content = content;
return this; 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) public ContentDialogBuilder WithDefaultButton(ContentDialogButton defaultButton)
{ {
_contentDialog.DefaultButton = defaultButton; _contentDialog.DefaultButton = (FluentAvalonia.UI.Controls.ContentDialogButton) defaultButton;
return this; 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) public ContentDialogBuilder HavingPrimaryButton(Action<ContentDialogButtonBuilder> configure)
{ {
ContentDialogButtonBuilder builder = new(); ContentDialogButtonBuilder builder = new();
@ -65,6 +88,11 @@ namespace Artemis.UI.Shared.Services.Builders
return this; 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) public ContentDialogBuilder HavingSecondaryButton(Action<ContentDialogButtonBuilder> configure)
{ {
ContentDialogButtonBuilder builder = new(); ContentDialogButtonBuilder builder = new();
@ -85,12 +113,24 @@ namespace Artemis.UI.Shared.Services.Builders
return this; 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) public ContentDialogBuilder WithCloseButtonText(string? text)
{ {
_contentDialog.CloseButtonText = text; _contentDialog.CloseButtonText = text;
return this; 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 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(); 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; 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() public async Task<ContentDialogResult> ShowAsync()
{ {
if (_parent.Content is not Panel panel) if (_parent.Content is not Panel panel)
@ -111,9 +156,9 @@ namespace Artemis.UI.Shared.Services.Builders
{ {
panel.Children.Add(_contentDialog); panel.Children.Add(_contentDialog);
ContentDialogResult result = await _contentDialog.ShowAsync(); ContentDialogResult result = await _contentDialog.ShowAsync();
// Take the dialog away from the VM in case it's going to try to hide it again or whatever... // Take the dialog away from the VM in case it's going to try to hide it again or whatever...
if (_viewModel != null) if (_viewModel != null)
_viewModel.ContentDialog = null; _viewModel.ContentDialog = null;
return result; return result;
@ -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 public class ContentDialogButtonBuilder
{ {
internal ContentDialogButtonBuilder() internal ContentDialogButtonBuilder()
@ -133,20 +207,48 @@ namespace Artemis.UI.Shared.Services.Builders
internal string? Text { get; set; } internal string? Text { get; set; }
internal ICommand? Command { get; set; } internal ICommand? Command { get; set; }
internal Action? Action { get; set; }
internal object? CommandParameter { 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) public ContentDialogButtonBuilder WithText(string? text)
{ {
Text = text; Text = text;
return this; 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) public ContentDialogButtonBuilder WithCommand(ICommand? command)
{ {
Command = command; Command = command;
return this; 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) public ContentDialogButtonBuilder WithCommandParameter(object? commandParameter)
{ {
CommandParameter = commandParameter; CommandParameter = commandParameter;

View File

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

View File

@ -12,6 +12,10 @@ namespace Artemis.UI.Shared.Services.Builders
private readonly OpenFileDialog _openFileDialog; private readonly OpenFileDialog _openFileDialog;
private readonly Window _parent; 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) public OpenFileDialogBuilder(Window parent)
{ {
_parent = parent; _parent = parent;
@ -67,7 +71,7 @@ namespace Artemis.UI.Shared.Services.Builders
} }
/// <summary> /// <summary>
/// Shows the file dialog /// Asynchronously shows the file dialog.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A task that on completion returns an array containing the full path to the selected /// 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 Window _parent;
private readonly SaveFileDialog _saveFileDialog; 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) public SaveFileDialogBuilder(Window parent)
{ {
_parent = parent; _parent = parent;
@ -67,7 +71,7 @@ namespace Artemis.UI.Shared.Services.Builders
} }
/// <summary> /// <summary>
/// Shows the save file dialog. /// Asynchronously shows the save file dialog.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A task that on completion contains the full path of the save location, or null if the /// 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 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 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(); NotificationBuilder CreateNotification();
} }
} }

View File

@ -5,30 +5,34 @@ using Avalonia.Controls;
namespace Artemis.UI.Shared.Services.Interfaces namespace Artemis.UI.Shared.Services.Interfaces
{ {
/// <summary>
/// A service that can be used to show windows and dialogs.
/// </summary>
public interface IWindowService : IArtemisSharedUIService public interface IWindowService : IArtemisSharedUIService
{ {
/// <summary> /// <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> /// </summary>
/// <typeparam name="TViewModel">The type of view model to create</typeparam> /// <typeparam name="TViewModel">The type of view model to create</typeparam>
/// <returns>The created view model</returns> /// <returns>The created view model</returns>
TViewModel ShowWindow<TViewModel>(params (string name, object value)[] parameters); TViewModel ShowWindow<TViewModel>(params (string name, object value)[] parameters);
/// <summary> /// <summary>
/// Given a ViewModel, show its corresponding View as a window /// Given a ViewModel, show its corresponding View as a window
/// </summary> /// </summary>
/// <param name="viewModel">ViewModel to show the View for</param> /// <param name="viewModel">ViewModel to show the View for</param>
void ShowWindow(object viewModel); void ShowWindow(object viewModel);
/// <summary> /// <summary>
/// Shows a dialog displaying the given exception /// Shows a dialog displaying the given exception
/// </summary> /// </summary>
/// <param name="title">The title of the dialog</param> /// <param name="title">The title of the dialog</param>
/// <param name="exception">The exception to display</param> /// <param name="exception">The exception to display</param>
void ShowExceptionDialog(string title, Exception exception); void ShowExceptionDialog(string title, Exception exception);
/// <summary> /// <summary>
/// Given an existing ViewModel, show its corresponding View as a Dialog /// Given an existing ViewModel, show its corresponding View as a Dialog
/// </summary> /// </summary>
/// <typeparam name="TResult">The return type</typeparam> /// <typeparam name="TResult">The return type</typeparam>
/// <param name="viewModel">ViewModel to show the View for</param> /// <param name="viewModel">ViewModel to show the View for</param>
@ -36,7 +40,8 @@ namespace Artemis.UI.Shared.Services.Interfaces
Task<TResult> ShowDialogAsync<TResult>(DialogViewModelBase<TResult> viewModel); Task<TResult> ShowDialogAsync<TResult>(DialogViewModelBase<TResult> viewModel);
/// <summary> /// <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> /// </summary>
/// <typeparam name="TViewModel">The view model type</typeparam> /// <typeparam name="TViewModel">The view model type</typeparam>
/// <typeparam name="TResult">The return type</typeparam> /// <typeparam name="TResult">The return type</typeparam>
@ -44,37 +49,40 @@ namespace Artemis.UI.Shared.Services.Interfaces
Task<TResult> ShowDialogAsync<TViewModel, TResult>(params (string name, object? value)[] parameters) where TViewModel : DialogViewModelBase<TResult>; Task<TResult> ShowDialogAsync<TViewModel, TResult>(params (string name, object? value)[] parameters) where TViewModel : DialogViewModelBase<TResult>;
/// <summary> /// <summary>
/// Shows a content dialog asking the user to confirm an action /// Shows a content dialog asking the user to confirm an action
/// </summary> /// </summary>
/// <param name="title">The title of the dialog</param> /// <param name="title">The title of the dialog</param>
/// <param name="message">The message 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="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> /// <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> /// <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"); Task<bool> ShowConfirmContentDialog(string title, string message, string confirm = "Confirm", string? cancel = "Cancel");
/// <summary> /// <summary>
/// Creates an open file dialog, use the fluent API to configure it /// Creates an open file dialog, use the fluent API to configure it
/// </summary> /// </summary>
/// <returns>The builder that can be used to configure the dialog</returns> /// <returns>The builder that can be used to configure the dialog</returns>
OpenFileDialogBuilder CreateOpenFileDialog(); OpenFileDialogBuilder CreateOpenFileDialog();
/// <summary> /// <summary>
/// Creates a save file dialog, use the fluent API to configure it /// Creates a save file dialog, use the fluent API to configure it
/// </summary> /// </summary>
/// <returns>The builder that can be used to configure the dialog</returns> /// <returns>The builder that can be used to configure the dialog</returns>
SaveFileDialogBuilder CreateSaveFileDialog(); SaveFileDialogBuilder CreateSaveFileDialog();
/// <summary> /// <summary>
/// Creates a content dialog, use the fluent API to configure it /// Creates a content dialog, use the fluent API to configure it
/// </summary> /// </summary>
/// <returns>The builder that can be used to configure the dialog</returns> /// <returns>The builder that can be used to configure the dialog</returns>
ContentDialogBuilder CreateContentDialog(); ContentDialogBuilder CreateContentDialog();
/// <summary> /// <summary>
/// Gets the current window of the application /// Gets the current window of the application
/// </summary> /// </summary>
/// <returns>The current window of the application</returns> /// <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 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 public interface IMainWindowService : IArtemisSharedUIService
{ {
/// <summary> /// <summary>

View File

@ -1,9 +1,10 @@
using Artemis.UI.Shared.Services.Builders; using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;
using Avalonia.Controls;
namespace Artemis.UI.Shared.Services namespace Artemis.UI.Shared.Services
{ {
public class NotificationService : INotificationService internal class NotificationService : INotificationService
{ {
private readonly IWindowService _windowService; private readonly IWindowService _windowService;
@ -14,7 +15,11 @@ namespace Artemis.UI.Shared.Services
public NotificationBuilder CreateNotification() 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() public async Task CopyException()
{ {
if (Application.Current?.Clipboard == null)
return;
await Application.Current.Clipboard.SetTextAsync(Exception.ToString()); await Application.Current.Clipboard.SetTextAsync(Exception.ToString());
_notificationService.CreateNotification() _notificationService.CreateNotification()
.WithMessage("Copied stack trace to clipboard.") .WithMessage("Copied stack trace to clipboard.")

View File

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

View File

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

View File

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

View File

@ -113,13 +113,13 @@ namespace Artemis.UI.Windows.Providers.Input
if (key == KeyboardKey.LeftCtrl && keyboardData.Keyboard.ScanCode == 56) if (key == KeyboardKey.LeftCtrl && keyboardData.Keyboard.ScanCode == 56)
return; 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 // Let the core know there is an identifier so it can store new identifications if applicable
if (identifier != null) if (identifier != null)
OnIdentifierReceived(identifier, InputDeviceType.Keyboard); OnIdentifierReceived(identifier, InputDeviceType.Keyboard);
ArtemisDevice device = null; ArtemisDevice? device = null;
if (identifier != null) if (identifier != null)
try try
{ {
@ -180,9 +180,10 @@ namespace Artemis.UI.Windows.Providers.Input
return; return;
} }
ArtemisDevice device = null; ArtemisDevice? device = null;
string identifier = data.Device?.DevicePath; string? identifier = data.Device?.DevicePath;
if (identifier != null) if (identifier != null)
{
try try
{ {
device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Mouse); 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"); _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}"); // 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(); 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. // Get the last error and display it.
int error = Marshal.GetLastWin32Error(); 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); private static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)] [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)] [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); 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 public class ColorToSolidColorBrushConverter : IValueConverter
{ {
/// <inheritdoc /> /// <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) return new SolidColorBrush(!(value is RGBColor color)
? new Color(0, 0, 0, 0) ? new Color(0, 0, 0, 0)
@ -20,7 +20,7 @@ namespace Artemis.UI.Converters
} }
/// <inheritdoc /> /// <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) return !(value is SolidColorBrush brush)
? RGBColor.Transparent ? 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 #region Implementation of IValueConverter
/// <inheritdoc /> /// <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(); return value?.ToString();
} }
/// <inheritdoc /> /// <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 parsedLedId;
return LedId.Unknown1; return LedId.Unknown1;
} }

View File

@ -8,7 +8,7 @@ namespace Artemis.UI.Converters
{ {
#region IValueConverter Members #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) if (value is double number)
return number * 100.0; return number * 100.0;
@ -16,7 +16,7 @@ namespace Artemis.UI.Converters
return value; 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) if (value is double number)
return number / 100.0; return number / 100.0;

View File

@ -7,14 +7,14 @@ namespace Artemis.UI.Converters
{ {
public class UriToFileNameConverter : IValueConverter 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) if (value is Uri uri && uri.IsFile)
return Path.GetFileName(uri.LocalPath); return Path.GetFileName(uri.LocalPath);
return null; 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; return value;
} }

View File

@ -9,8 +9,10 @@ namespace Artemis.UI.Converters
public class ValuesAdditionConverter : IMultiValueConverter public class ValuesAdditionConverter : IMultiValueConverter
{ {
/// <inheritdoc /> /// <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(); 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 Bitmap? _currentFrame;
private string? _frameTargetPath; private string? _frameTargetPath;
private string _renderer; private string? _renderer;
private int _renderHeight; private int _renderHeight;
private int _renderWidth; private int _renderWidth;
@ -56,7 +56,7 @@ namespace Artemis.UI.Screens.Debugger.Render
set => this.RaiseAndSetIfChanged(ref _renderHeight, value); set => this.RaiseAndSetIfChanged(ref _renderHeight, value);
} }
public string Renderer public string? Renderer
{ {
get => _renderer; get => _renderer;
set => this.RaiseAndSetIfChanged(ref _renderer, value); set => this.RaiseAndSetIfChanged(ref _renderer, value);

View File

@ -28,6 +28,9 @@ namespace Artemis.UI.Screens.Device
public async Task CopyToClipboard(string content) public async Task CopyToClipboard(string content)
{ {
if (Application.Current?.Clipboard == null)
return;
await Application.Current.Clipboard.SetTextAsync(content); await Application.Current.Clipboard.SetTextAsync(content);
_notificationService.CreateNotification().WithMessage("Copied path to clipboard.").Show(); _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 IRgbService _rgbService;
private readonly IInputService _inputService; private readonly IInputService _inputService;
private readonly ObservableCollection<ArtemisLed> _selectedLeds; private readonly ObservableCollection<ArtemisLed> _selectedLeds;
private ArtemisLed _selectedLed; private ArtemisLed? _selectedLed;
public InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds, IRgbService rgbService, IInputService inputService) 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 ArtemisDevice Device { get; }
public ArtemisLed SelectedLed public ArtemisLed? SelectedLed
{ {
get => _selectedLed; get => _selectedLed;
set => this.RaiseAndSetIfChanged(ref _selectedLed, value); 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); bool foundLedId = InputKeyUtilities.KeyboardKeyLedIdMap.TryGetValue(e.Key, out LedId ledId);
if (!foundLedId) if (!foundLedId)
return; return;
ArtemisLed artemisLed = Device.GetLed(ledId, false); ArtemisLed? artemisLed = Device.GetLed(ledId, false);
if (artemisLed == null) if (artemisLed == null)
return; return;

View File

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

View File

@ -69,7 +69,7 @@ namespace Artemis.UI.Screens.Settings
SearchPluginInput = plugin.Info.Name; SearchPluginInput = plugin.Info.Name;
// Enable it via the VM to enable the prerequisite dialog // 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}) if (pluginViewModel is {IsEnabled: false})
pluginViewModel.IsEnabled = true; pluginViewModel.IsEnabled = true;

View File

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

View File

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

View File

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

View File

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