diff --git a/CHANGELIST.md b/CHANGELIST.md index 29fdf73d..4d91f82f 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -11,6 +11,7 @@ - Remove all but .NET 6 for AppVeyor packaging - Place message boxes at center of main window (Deterous) - Enable nullability in MPF +- Enable nullability in MPF.UI.Core ### 2.7.0 (2023-10-11) diff --git a/MPF.Core/Data/Options.cs b/MPF.Core/Data/Options.cs index 8a283a25..91666c21 100644 --- a/MPF.Core/Data/Options.cs +++ b/MPF.Core/Data/Options.cs @@ -628,12 +628,16 @@ namespace MPF.Core.Data /// Constructor taking an existing Options object /// /// +#if NET48 public Options(Options source) +#else + public Options(Options? source) +#endif { #if NET48 - Settings = new Dictionary(source.Settings); + Settings = new Dictionary(source?.Settings ?? new Dictionary()); #else - Settings = new Dictionary(source.Settings); + Settings = new Dictionary(source?.Settings ?? new Dictionary()); #endif } diff --git a/MPF.Core/UI/ViewModels/DiscInformationViewModel.cs b/MPF.Core/UI/ViewModels/DiscInformationViewModel.cs index fdfafe8e..fe768be0 100644 --- a/MPF.Core/UI/ViewModels/DiscInformationViewModel.cs +++ b/MPF.Core/UI/ViewModels/DiscInformationViewModel.cs @@ -191,10 +191,14 @@ namespace MPF.Core.UI.ViewModels /// /// Constructor /// +#if NET48 public DiscInformationViewModel(Options options, SubmissionInfo submissionInfo) +#else + public DiscInformationViewModel(Options options, SubmissionInfo? submissionInfo) +#endif { Options = options; - SubmissionInfo = submissionInfo.Clone() as SubmissionInfo ?? new SubmissionInfo(); + SubmissionInfo = submissionInfo?.Clone() as SubmissionInfo ?? new SubmissionInfo(); } #region Helpers diff --git a/MPF.Core/UI/ViewModels/MainViewModel.cs b/MPF.Core/UI/ViewModels/MainViewModel.cs index 33b09dd7..74cc3b90 100644 --- a/MPF.Core/UI/ViewModels/MainViewModel.cs +++ b/MPF.Core/UI/ViewModels/MainViewModel.cs @@ -981,7 +981,11 @@ namespace MPF.Core.UI.ViewModels /// /// Indicates if the settings were saved or not /// Options representing the new, saved values +#if NET48 public void UpdateOptions(bool savedSettings, Data.Options newOptions) +#else + public void UpdateOptions(bool savedSettings, Data.Options? newOptions) +#endif { if (savedSettings) { @@ -990,7 +994,7 @@ namespace MPF.Core.UI.ViewModels } } - #endregion +#endregion #region UI Functionality diff --git a/MPF.UI.Core/ElementConverter.cs b/MPF.UI.Core/ElementConverter.cs index 457922ba..600e42ef 100644 --- a/MPF.UI.Core/ElementConverter.cs +++ b/MPF.UI.Core/ElementConverter.cs @@ -30,7 +30,11 @@ namespace MPF.UI.Core } } +#if NET48 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) +#else + public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) +#endif { // If it's an IElement but ends up null var element = value as IElement; diff --git a/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBox.cs b/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBox.cs index 089e7a6e..791d02a9 100644 --- a/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBox.cs +++ b/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBox.cs @@ -173,7 +173,11 @@ namespace WPFCustomMessageBox /// /// If the message box closes automatically due to the being exceeded, this result is returned. /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user. +#if NET48 public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None) +#else + public static MessageBoxResult Show(Window owner, string? messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None) +#endif { switch (button) { @@ -515,7 +519,11 @@ namespace WPFCustomMessageBox /// The message box will close automatically after given milliseconds /// If the message box closes automatically due to being exceeded, this result is returned. /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user. +#if NET48 private static MessageBoxResult ShowOKMessage(Window owner, string messageBoxText, string caption, string okButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None) +#else + private static MessageBoxResult ShowOKMessage(Window? owner, string? messageBoxText, string caption, string? okButtonText, string? cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None) +#endif { MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.OK : MessageBoxButton.OKCancel; @@ -545,7 +553,11 @@ namespace WPFCustomMessageBox /// The message box will close automatically after given milliseconds /// If the message box closes automatically due to being exceeded, this result is returned. /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user. +#if NET48 private static MessageBoxResult ShowYesNoMessage(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None) +#else + private static MessageBoxResult ShowYesNoMessage(Window? owner, string? messageBoxText, string caption, string? yesButtonText, string? noButtonText, string? cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None) +#endif { MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.YesNo : MessageBoxButton.YesNoCancel; diff --git a/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs b/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs index 5630d47f..72952708 100644 --- a/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs +++ b/MPF.UI.Core/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs @@ -12,7 +12,11 @@ namespace WPFCustomMessageBox { private bool _removeTitleBarIcon = true; +#if NET48 public string Caption +#else + public string? Caption +#endif { get { @@ -24,7 +28,11 @@ namespace WPFCustomMessageBox } } +#if NET48 public string Message +#else + public string? Message +#endif { get { @@ -36,7 +44,11 @@ namespace WPFCustomMessageBox } } +#if NET48 public string OkButtonText +#else + public string? OkButtonText +#endif { get { @@ -48,7 +60,11 @@ namespace WPFCustomMessageBox } } +#if NET48 public string CancelButtonText +#else + public string? CancelButtonText +#endif { get { @@ -60,7 +76,11 @@ namespace WPFCustomMessageBox } } +#if NET48 public string YesButtonText +#else + public string? YesButtonText +#endif { get { @@ -72,7 +92,11 @@ namespace WPFCustomMessageBox } } +#if NET48 public string NoButtonText +#else + public string? NoButtonText +#endif { get { @@ -86,7 +110,11 @@ namespace WPFCustomMessageBox public MessageBoxResult Result { get; set; } +#if NET48 internal CustomMessageBoxWindow(Window owner, string message, string caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true) +#else + internal CustomMessageBoxWindow(Window? owner, string? message, string? caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true) +#endif { InitializeComponent(); diff --git a/MPF.UI.Core/External/WPFCustomMessageBox/Util.cs b/MPF.UI.Core/External/WPFCustomMessageBox/Util.cs index 24d6de55..ea64f77c 100644 --- a/MPF.UI.Core/External/WPFCustomMessageBox/Util.cs +++ b/MPF.UI.Core/External/WPFCustomMessageBox/Util.cs @@ -60,7 +60,11 @@ namespace WPFCustomMessageBox /// /// /// +#if NET48 internal static string TryAddKeyboardAccellerator(this string input) +#else + internal static string? TryAddKeyboardAccellerator(this string? input) +#endif { if (input == null) return input; diff --git a/MPF.UI.Core/MPF.UI.Core.csproj b/MPF.UI.Core/MPF.UI.Core.csproj index 51c09f2b..4438f777 100644 --- a/MPF.UI.Core/MPF.UI.Core.csproj +++ b/MPF.UI.Core/MPF.UI.Core.csproj @@ -10,6 +10,10 @@ 2.7.0 + + enable + + diff --git a/MPF.UI.Core/Theme.cs b/MPF.UI.Core/Theme.cs index 798da485..238c0dcc 100644 --- a/MPF.UI.Core/Theme.cs +++ b/MPF.UI.Core/Theme.cs @@ -6,39 +6,63 @@ namespace MPF.UI.Core /// /// Represents all required mapping values for the UI /// - public class Theme + public abstract class Theme { #region Application-Wide /// /// SolidColorBrush used to paint the active window's border. /// - public SolidColorBrush ActiveBorderBrush { get; set; } +#if NET48 + public SolidColorBrush ActiveBorderBrush { get; protected set; } +#else + public SolidColorBrush? ActiveBorderBrush { get; protected set; } +#endif /// /// SolidColorBrush that paints the face of a three-dimensional display element. /// - public SolidColorBrush ControlBrush { get; set; } +#if NET48 + public SolidColorBrush ControlBrush { get; protected set; } +#else + public SolidColorBrush? ControlBrush { get; protected set; } +#endif /// /// SolidColorBrush that paints text in a three-dimensional display element. /// - public SolidColorBrush ControlTextBrush { get; set; } +#if NET48 + public SolidColorBrush ControlTextBrush { get; protected set; } +#else + public SolidColorBrush? ControlTextBrush { get; protected set; } +#endif /// /// SolidColorBrush that paints disabled text. /// - public SolidColorBrush GrayTextBrush { get; set; } +#if NET48 + public SolidColorBrush GrayTextBrush { get; protected set; } +#else + public SolidColorBrush? GrayTextBrush { get; protected set; } +#endif /// /// SolidColorBrush that paints the background of a window's client area. /// - public SolidColorBrush WindowBrush { get; set; } +#if NET48 + public SolidColorBrush WindowBrush { get; protected set; } +#else + public SolidColorBrush? WindowBrush { get; protected set; } +#endif /// /// SolidColorBrush that paints the text in the client area of a window. /// - public SolidColorBrush WindowTextBrush { get; set; } +#if NET48 + public SolidColorBrush WindowTextBrush { get; protected set; } +#else + public SolidColorBrush? WindowTextBrush { get; protected set; } +#endif #endregion @@ -47,22 +71,38 @@ namespace MPF.UI.Core /// /// Brush for the Button.Disabled.Background resource /// - public Brush Button_Disabled_Background { get; set; } +#if NET48 + public Brush Button_Disabled_Background { get; protected set; } +#else + public Brush? Button_Disabled_Background { get; protected set; } +#endif /// /// Brush for the Button.MouseOver.Background resource /// - public Brush Button_MouseOver_Background { get; set; } +#if NET48 + public Brush Button_MouseOver_Background { get; protected set; } +#else + public Brush? Button_MouseOver_Background { get; protected set; } +#endif /// /// Brush for the Button.Pressed.Background resource /// - public Brush Button_Pressed_Background { get; set; } +#if NET48 + public Brush Button_Pressed_Background { get; protected set; } +#else + public Brush? Button_Pressed_Background { get; protected set; } +#endif /// /// Brush for the Button.Static.Background resource /// - public Brush Button_Static_Background { get; set; } +#if NET48 + public Brush Button_Static_Background { get; protected set; } +#else + public Brush? Button_Static_Background { get; protected set; } +#endif #endregion @@ -71,62 +111,110 @@ namespace MPF.UI.Core /// /// Brush for the ComboBox.Disabled.Background resource /// - public Brush ComboBox_Disabled_Background { get; set; } +#if NET48 + public Brush ComboBox_Disabled_Background { get; protected set; } +#else + public Brush? ComboBox_Disabled_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.Disabled.Editable.Background resource /// - public Brush ComboBox_Disabled_Editable_Background { get; set; } +#if NET48 + public Brush ComboBox_Disabled_Editable_Background { get; protected set; } +#else + public Brush? ComboBox_Disabled_Editable_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.Disabled.Editable.Button.Background resource /// - public Brush ComboBox_Disabled_Editable_Button_Background { get; set; } +#if NET48 + public Brush ComboBox_Disabled_Editable_Button_Background { get; protected set; } +#else + public Brush? ComboBox_Disabled_Editable_Button_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.MouseOver.Background resource /// - public Brush ComboBox_MouseOver_Background { get; set; } +#if NET48 + public Brush ComboBox_MouseOver_Background { get; protected set; } +#else + public Brush? ComboBox_MouseOver_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.MouseOver.Editable.Background resource /// - public Brush ComboBox_MouseOver_Editable_Background { get; set; } +#if NET48 + public Brush ComboBox_MouseOver_Editable_Background { get; protected set; } +#else + public Brush? ComboBox_MouseOver_Editable_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.MouseOver.Editable.Button.Background resource /// - public Brush ComboBox_MouseOver_Editable_Button_Background { get; set; } +#if NET48 + public Brush ComboBox_MouseOver_Editable_Button_Background { get; protected set; } +#else + public Brush? ComboBox_MouseOver_Editable_Button_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.Pressed.Background resource /// - public Brush ComboBox_Pressed_Background { get; set; } +#if NET48 + public Brush ComboBox_Pressed_Background { get; protected set; } +#else + public Brush? ComboBox_Pressed_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.Pressed.Editable.Background resource /// - public Brush ComboBox_Pressed_Editable_Background { get; set; } +#if NET48 + public Brush ComboBox_Pressed_Editable_Background { get; protected set; } +#else + public Brush? ComboBox_Pressed_Editable_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.Pressed.Editable.Button.Background resource /// - public Brush ComboBox_Pressed_Editable_Button_Background { get; set; } +#if NET48 + public Brush ComboBox_Pressed_Editable_Button_Background { get; protected set; } +#else + public Brush? ComboBox_Pressed_Editable_Button_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.Static.Background resource /// - public Brush ComboBox_Static_Background { get; set; } +#if NET48 + public Brush ComboBox_Static_Background { get; protected set; } +#else + public Brush? ComboBox_Static_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.Static.Editable.Background resource /// - public Brush ComboBox_Static_Editable_Background { get; set; } +#if NET48 + public Brush ComboBox_Static_Editable_Background { get; protected set; } +#else + public Brush? ComboBox_Static_Editable_Background { get; protected set; } +#endif /// /// Brush for the ComboBox.Static.Editable.Button.Background resource /// - public Brush ComboBox_Static_Editable_Button_Background { get; set; } +#if NET48 + public Brush ComboBox_Static_Editable_Button_Background { get; protected set; } +#else + public Brush? ComboBox_Static_Editable_Button_Background { get; protected set; } +#endif #endregion @@ -135,7 +223,11 @@ namespace MPF.UI.Core /// /// Brush for the CustomMessageBox.Static.Background resource /// - public Brush CustomMessageBox_Static_Background { get; set; } +#if NET48 + public Brush CustomMessageBox_Static_Background { get; protected set; } +#else + public Brush? CustomMessageBox_Static_Background { get; protected set; } +#endif #endregion @@ -144,12 +236,20 @@ namespace MPF.UI.Core /// /// Brush for the MenuItem.SubMenu.Background resource /// - public Brush MenuItem_SubMenu_Background { get; set; } +#if NET48 + public Brush MenuItem_SubMenu_Background { get; protected set; } +#else + public Brush? MenuItem_SubMenu_Background { get; protected set; } +#endif /// /// Brush for the MenuItem.SubMenu.Border resource /// - public Brush MenuItem_SubMenu_Border { get; set; } +#if NET48 + public Brush MenuItem_SubMenu_Border { get; protected set; } +#else + public Brush? MenuItem_SubMenu_Border { get; protected set; } +#endif #endregion @@ -158,7 +258,11 @@ namespace MPF.UI.Core /// /// Brush for the ProgressBar.Background resource /// - public Brush ProgressBar_Background { get; set; } +#if NET48 + public Brush ProgressBar_Background { get; protected set; } +#else + public Brush? ProgressBar_Background { get; protected set; } +#endif #endregion @@ -167,7 +271,11 @@ namespace MPF.UI.Core /// /// Brush for the ScrollViewer.ScrollBar.Background resource /// - public Brush ScrollViewer_ScrollBar_Background { get; set; } +#if NET48 + public Brush ScrollViewer_ScrollBar_Background { get; protected set; } +#else + public Brush? ScrollViewer_ScrollBar_Background { get; protected set; } +#endif #endregion @@ -176,17 +284,29 @@ namespace MPF.UI.Core /// /// Brush for the TabItem.Selected.Background resource /// - public Brush TabItem_Selected_Background { get; set; } +#if NET48 + public Brush TabItem_Selected_Background { get; protected set; } +#else + public Brush? TabItem_Selected_Background { get; protected set; } +#endif /// /// Brush for the TabItem.Static.Background resource /// - public Brush TabItem_Static_Background { get; set; } +#if NET48 + public Brush TabItem_Static_Background { get; protected set; } +#else + public Brush? TabItem_Static_Background { get; protected set; } +#endif /// /// Brush for the TabItem.Static.Border resource /// - public Brush TabItem_Static_Border { get; set; } +#if NET48 + public Brush TabItem_Static_Border { get; protected set; } +#else + public Brush? TabItem_Static_Border { get; protected set; } +#endif #endregion @@ -195,7 +315,11 @@ namespace MPF.UI.Core /// /// Brush for the TextBox.Static.Background resource /// - public Brush TextBox_Static_Background { get; set; } +#if NET48 + public Brush TextBox_Static_Background { get; protected set; } +#else + public Brush? TextBox_Static_Background { get; protected set; } +#endif #endregion diff --git a/MPF.UI.Core/UserControls/LogOutput.xaml.cs b/MPF.UI.Core/UserControls/LogOutput.xaml.cs index 7ba86777..22ed8190 100644 --- a/MPF.UI.Core/UserControls/LogOutput.xaml.cs +++ b/MPF.UI.Core/UserControls/LogOutput.xaml.cs @@ -29,7 +29,11 @@ namespace MPF.UI.Core.UserControls /// /// Cached value of the last line written /// +#if NET48 private Run lastLine = null; +#else + private Run? lastLine = null; +#endif public LogOutput() { @@ -164,6 +168,7 @@ namespace MPF.UI.Core.UserControls { Dispatcher.Invoke(() => { + if (lastLine == null) lastLine = new Run(); lastLine.Text = logLine.Text; lastLine.Foreground = logLine.GetForegroundColor(); }); diff --git a/MPF.UI.Core/Windows/DiscInformationWindow.xaml.cs b/MPF.UI.Core/Windows/DiscInformationWindow.xaml.cs index 2ad08719..64bfa0b1 100644 --- a/MPF.UI.Core/Windows/DiscInformationWindow.xaml.cs +++ b/MPF.UI.Core/Windows/DiscInformationWindow.xaml.cs @@ -15,12 +15,16 @@ namespace MPF.UI.Core.Windows /// /// Read-only access to the current disc information view model /// - public DiscInformationViewModel DiscInformationViewModel => DataContext as DiscInformationViewModel; + public DiscInformationViewModel DiscInformationViewModel => DataContext as DiscInformationViewModel ?? new DiscInformationViewModel(new Options(), new SubmissionInfo()); /// /// Constructor /// +#if NET48 public DiscInformationWindow(Options options, SubmissionInfo submissionInfo) +#else + public DiscInformationWindow(Options options, SubmissionInfo? submissionInfo) +#endif { InitializeComponent(); DataContext = new DiscInformationViewModel(options, submissionInfo); @@ -47,7 +51,11 @@ namespace MPF.UI.Core.Windows /// /// Manipulate fields based on the current disc /// +#if NET48 private void ManipulateFields(Options options, SubmissionInfo submissionInfo) +#else + private void ManipulateFields(Options options, SubmissionInfo? submissionInfo) +#endif { // Enable tabs in all fields, if required if (options.EnableTabsInInputFields) @@ -115,63 +123,71 @@ namespace MPF.UI.Core.Windows /// /// TODO: Figure out how to bind the PartiallyMatchedIDs array to a text box /// TODO: Convert visibility to a binding +#if NET48 private void HideReadOnlyFields(SubmissionInfo submissionInfo) +#else + private void HideReadOnlyFields(SubmissionInfo? submissionInfo) +#endif { - if (submissionInfo?.FullyMatchedID == null) + // If there's no submission information + if (submissionInfo == null) + return; + + if (submissionInfo.FullyMatchedID == null) FullyMatchedID.Visibility = Visibility.Collapsed; - if (submissionInfo?.PartiallyMatchedIDs == null) + if (submissionInfo.PartiallyMatchedIDs == null) PartiallyMatchedIDs.Visibility = Visibility.Collapsed; else PartiallyMatchedIDs.Text = string.Join(", ", submissionInfo.PartiallyMatchedIDs); - if (submissionInfo?.CopyProtection?.AntiModchip == null) + if (submissionInfo.CopyProtection?.AntiModchip == null) AntiModchip.Visibility = Visibility.Collapsed; - if (submissionInfo?.TracksAndWriteOffsets?.OtherWriteOffsets == null) + if (submissionInfo.TracksAndWriteOffsets?.OtherWriteOffsets == null) DiscOffset.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.DMIHash) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys?.Contains(SiteCode.DMIHash) != true) DMIHash.Visibility = Visibility.Collapsed; - if (submissionInfo?.EDC?.EDC == null) + if (submissionInfo.EDC?.EDC == null) EDC.Visibility = Visibility.Collapsed; - if (string.IsNullOrWhiteSpace(submissionInfo?.CommonDiscInfo?.ErrorsCount)) + if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.ErrorsCount)) ErrorsCount.Visibility = Visibility.Collapsed; - if (string.IsNullOrWhiteSpace(submissionInfo?.CommonDiscInfo?.EXEDateBuildDate)) + if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.EXEDateBuildDate)) EXEDateBuildDate.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.Filename) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.Filename) != true) Filename.Visibility = Visibility.Collapsed; - if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.Header)) + if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.Header)) Header.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalName) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.InternalName) != true) InternalName.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalSerialName) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.InternalSerialName) != true) InternalSerialName.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.Multisession) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.Multisession) != true) Multisession.Visibility = Visibility.Collapsed; - if (submissionInfo?.CopyProtection?.LibCrypt == null) + if (submissionInfo.CopyProtection?.LibCrypt == null) LibCrypt.Visibility = Visibility.Collapsed; - if (string.IsNullOrWhiteSpace(submissionInfo?.CopyProtection?.LibCryptData)) + if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.LibCryptData)) LibCryptData.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.PFIHash) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.PFIHash) != true) PFIHash.Visibility = Visibility.Collapsed; - if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.PIC)) + if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PIC)) PIC.Visibility = Visibility.Collapsed; - if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.PVD)) + if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PVD)) PVD.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.RingNonZeroDataStart) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.RingNonZeroDataStart) != true) RingNonZeroDataStart.Visibility = Visibility.Collapsed; - if (string.IsNullOrWhiteSpace(submissionInfo?.CopyProtection?.SecuROMData)) + if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.SecuROMData)) SecuROMData.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSHash) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.SSHash) != true) SSHash.Visibility = Visibility.Collapsed; - if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.SecuritySectorRanges)) + if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.SecuritySectorRanges)) SecuritySectorRanges.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSVersion) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.SSVersion) != true) SSVersion.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.UniversalHash) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.UniversalHash) != true) UniversalHash.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.VolumeLabel) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.VolumeLabel) != true) VolumeLabel.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XeMID) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.XeMID) != true) XeMID.Visibility = Visibility.Collapsed; - if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XMID) != true) + if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys.Contains(SiteCode.XMID) != true) XMID.Visibility = Visibility.Collapsed; } @@ -179,7 +195,11 @@ namespace MPF.UI.Core.Windows /// Update visible fields and sections based on the media type /// /// TODO: See if these can be done by binding +#if NET48 private void UpdateFromDiscType(SubmissionInfo submissionInfo) +#else + private void UpdateFromDiscType(SubmissionInfo? submissionInfo) +#endif { // Sony-printed discs have layers in the opposite order var system = submissionInfo?.CommonDiscInfo?.System; @@ -326,7 +346,11 @@ namespace MPF.UI.Core.Windows /// Update visible fields and sections based on the system type /// /// TODO: See if these can be done by binding +#if NET48 private void UpdateFromSystemType(SubmissionInfo submissionInfo) +#else + private void UpdateFromSystemType(SubmissionInfo? submissionInfo) +#endif { var system = submissionInfo?.CommonDiscInfo?.System; switch (system) @@ -337,7 +361,7 @@ namespace MPF.UI.Core.Windows } } - #endregion +#endregion #region Event Handlers diff --git a/MPF.UI.Core/Windows/MainWindow.xaml.cs b/MPF.UI.Core/Windows/MainWindow.xaml.cs index 9b6d7fa9..683b963a 100644 --- a/MPF.UI.Core/Windows/MainWindow.xaml.cs +++ b/MPF.UI.Core/Windows/MainWindow.xaml.cs @@ -15,7 +15,7 @@ namespace MPF.UI.Core.Windows /// /// Read-only access to the current main view model /// - public MainViewModel MainViewModel => DataContext as MainViewModel; + public MainViewModel MainViewModel => DataContext as MainViewModel ?? new MainViewModel(); /// /// Constructor @@ -95,8 +95,10 @@ namespace MPF.UI.Core.Windows { // Get the current path, if possible string currentPath = MainViewModel.OutputPath; - if (string.IsNullOrWhiteSpace(currentPath)) + if (string.IsNullOrWhiteSpace(currentPath) && !string.IsNullOrWhiteSpace(MainViewModel.Options.DefaultOutputPath)) currentPath = Path.Combine(MainViewModel.Options.DefaultOutputPath, "track.bin"); + else if (string.IsNullOrWhiteSpace(currentPath)) + currentPath = "track.bin"; if (string.IsNullOrWhiteSpace(currentPath)) currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "track.bin"); @@ -104,7 +106,7 @@ namespace MPF.UI.Core.Windows currentPath = Path.GetFullPath(currentPath); // Get the directory - string directory = Path.GetDirectoryName(currentPath); + var directory = Path.GetDirectoryName(currentPath); // Get the filename string filename = Path.GetFileName(currentPath); @@ -128,7 +130,7 @@ namespace MPF.UI.Core.Windows /// True to show the box even if it's the same, false to only show if it's different public void CheckForUpdates(bool showIfSame) { - (bool different, string message, string url) = MainViewModel.CheckForUpdates(); + (bool different, string message, var url) = MainViewModel.CheckForUpdates(); // If we have a new version, put it in the clipboard if (different) @@ -204,7 +206,11 @@ namespace MPF.UI.Core.Windows /// /// SubmissionInfo object to display and possibly change /// Dialog open result +#if NET48 public (bool?, SubmissionInfo) ShowDiscInformationWindow(SubmissionInfo submissionInfo) +#else + public (bool?, SubmissionInfo?) ShowDiscInformationWindow(SubmissionInfo? submissionInfo) +#endif { if (MainViewModel.Options.ShowDiscEjectReminder) CustomMessageBox.Show(this, "It is now safe to eject the disc", "Eject", MessageBoxButton.OK, MessageBoxImage.Information); @@ -221,9 +227,17 @@ namespace MPF.UI.Core.Windows // Copy back the submission info changes, if necessary if (result == true) +#if NET48 submissionInfo = discInformationWindow.DiscInformationViewModel.SubmissionInfo.Clone() as SubmissionInfo; +#else + submissionInfo = (discInformationWindow.DiscInformationViewModel.SubmissionInfo.Clone() as SubmissionInfo)!; +#endif +#if NET48 return (result, submissionInfo); +#else + return (result, submissionInfo!); +#endif } /// @@ -268,10 +282,14 @@ namespace MPF.UI.Core.Windows /// /// Handler for OptionsWindow OnUpdated event /// +#if NET48 public void OnOptionsUpdated(object sender, EventArgs e) +#else + public void OnOptionsUpdated(object? sender, EventArgs e) +#endif { bool savedSettings = (sender as OptionsWindow)?.OptionsViewModel?.SavedSettings ?? false; - var options = (sender as OptionsWindow).OptionsViewModel.Options; + var options = (sender as OptionsWindow)?.OptionsViewModel?.Options; MainViewModel.UpdateOptions(savedSettings, options); } @@ -319,11 +337,11 @@ namespace MPF.UI.Core.Windows /// public async void CopyProtectScanButtonClick(object sender, RoutedEventArgs e) { - (string output, string error) = await MainViewModel.ScanAndShowProtection(); + var (output, error) = await MainViewModel.ScanAndShowProtection(); if (!MainViewModel.LogPanelExpanded) { - if (string.IsNullOrEmpty(error)) + if (!string.IsNullOrEmpty(output) && string.IsNullOrEmpty(error)) CustomMessageBox.Show(this, output, "Detected Protection(s)", MessageBoxButton.OK, MessageBoxImage.Information); else CustomMessageBox.Show(this, "An exception occurred, see the log for details", "Error!", MessageBoxButton.OK, MessageBoxImage.Error); diff --git a/MPF.UI.Core/Windows/OptionsWindow.xaml.cs b/MPF.UI.Core/Windows/OptionsWindow.xaml.cs index 036abc04..c2c50b65 100644 --- a/MPF.UI.Core/Windows/OptionsWindow.xaml.cs +++ b/MPF.UI.Core/Windows/OptionsWindow.xaml.cs @@ -17,7 +17,7 @@ namespace MPF.UI.Core.Windows /// /// Read-only access to the current options view model /// - public OptionsViewModel OptionsViewModel => DataContext as OptionsViewModel; + public OptionsViewModel OptionsViewModel => DataContext as OptionsViewModel ?? new OptionsViewModel(new Options()); /// /// Constructor @@ -46,7 +46,11 @@ namespace MPF.UI.Core.Windows /// /// Browse and set a path based on the invoking button /// +#if NET48 private void BrowseForPath(Window parent, System.Windows.Controls.Button button) +#else + private void BrowseForPath(Window parent, System.Windows.Controls.Button? button) +#endif { // If the button is null, we can't do anything if (button == null) @@ -58,8 +62,8 @@ namespace MPF.UI.Core.Windows // TODO: hack for now, then we'll see bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath"; - string currentPath = TextBoxForPathSetting(parent, pathSettingName)?.Text; - string initialDirectory = AppDomain.CurrentDomain.BaseDirectory; + var currentPath = TextBoxForPathSetting(parent, pathSettingName)?.Text; + var initialDirectory = AppDomain.CurrentDomain.BaseDirectory; if (!shouldBrowseForPath && !string.IsNullOrEmpty(currentPath)) initialDirectory = Path.GetDirectoryName(Path.GetFullPath(currentPath)); @@ -88,7 +92,9 @@ namespace MPF.UI.Core.Windows if (exists) { OptionsViewModel.Options[pathSettingName] = path; - TextBoxForPathSetting(parent, pathSettingName).Text = path; + var textBox = TextBoxForPathSetting(parent, pathSettingName); + if (textBox != null) + textBox.Text = path; } else { @@ -108,7 +114,11 @@ namespace MPF.UI.Core.Windows /// /// Setting name to find /// TextBox for that setting +#if NET48 private System.Windows.Controls.TextBox TextBoxForPathSetting(Window parent, string name) => +#else + private System.Windows.Controls.TextBox? TextBoxForPathSetting(Window parent, string name) => +#endif parent.FindName(name + "TextBox") as System.Windows.Controls.TextBox; /// @@ -119,7 +129,11 @@ namespace MPF.UI.Core.Windows /// /// Create an open file dialog box /// +#if NET48 private static OpenFileDialog CreateOpenFileDialog(string initialDirectory) +#else + private static OpenFileDialog CreateOpenFileDialog(string? initialDirectory) +#endif { return new OpenFileDialog() { @@ -142,7 +156,7 @@ namespace MPF.UI.Core.Windows #if NET48 (bool? success, string message) = OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password); #else - (bool? success, string message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password); + (bool? success, string? message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password); #endif if (success == true) diff --git a/MPF/MPF.csproj b/MPF/MPF.csproj index 1b05f073..a6ddc624 100644 --- a/MPF/MPF.csproj +++ b/MPF/MPF.csproj @@ -15,9 +15,9 @@ MPF.Test - - enable - + + enable +