From bf45d77a1ac3f4eb0d1f4e0abd6bc35a567f4185 Mon Sep 17 00:00:00 2001 From: Hugh Bellamy Date: Tue, 16 Apr 2019 17:50:37 +0100 Subject: [PATCH 1/3] Cleanup misc Design classes --- .../Runtime/InteropServices/UCOMITypeLib.cs | 30 +++++++ .../System/Windows/Forms/Design/AxImporter.cs | 79 +++++++++---------- .../Windows/Forms/Design/DesignerOptions.cs | 71 ++++++----------- .../Windows/Forms/Design/MenuCommands.cs | 29 +++---- .../Windows/Forms/Design/StandardGroups.cs | 5 +- .../Forms/Design/ThemedScrollbarMode.cs | 8 -- .../Forms/Design/ThemedScrollbarWindow.cs | 12 +++ .../WindowsFormsDesignerOptionService.cs | 18 +---- 8 files changed, 118 insertions(+), 134 deletions(-) create mode 100644 src/System.Windows.Forms.Design/src/System/Runtime/InteropServices/UCOMITypeLib.cs create mode 100644 src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarWindow.cs diff --git a/src/System.Windows.Forms.Design/src/System/Runtime/InteropServices/UCOMITypeLib.cs b/src/System.Windows.Forms.Design/src/System/Runtime/InteropServices/UCOMITypeLib.cs new file mode 100644 index 00000000000..8e222217022 --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Runtime/InteropServices/UCOMITypeLib.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices.ComTypes; + +namespace System.Runtime.InteropServices +{ + // UCOMITypeLib is not yet ported to interop on core. + [Guid("00020402-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface UCOMITypeLib + { + [PreserveSig] + int GetTypeInfoCount(); + + void GetTypeInfoType(int index, out TYPEKIND pTKind); + + void GetLibAttr(out IntPtr ppTLibAttr); + + void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile); + + [return: MarshalAs(UnmanagedType.Bool)] + bool IsName([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal); + + [PreserveSig] + void ReleaseTLibAttr(IntPtr pTLibAttr); + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AxImporter.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AxImporter.cs index a4306573745..77c40c7f95e 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AxImporter.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/AxImporter.cs @@ -10,10 +10,7 @@ namespace System.Windows.Forms.Design { /// - /// - /// Imports ActiveX controls and generates a wrapper that can be accessed by a - /// designer. - /// + /// Imports ActiveX controls and generates a wrapper that can be accessed by a designer. /// public class AxImporter { @@ -21,60 +18,91 @@ public AxImporter(Options options) { throw new NotImplementedException(SR.NotImplementedByDesign); } + public sealed class Options { + /// /// The flag that controls when we sign the generated assemblies. + /// public bool delaySign = false; + /// /// Flag that controls whether we are to generate sources for the ActiveX control wrapper. + /// public bool genSources = false; + /// /// Regardless of which version of the library is registered, if at all, use the /// path supplied on the command line for AxImp to generate the Windows Forms wrappers. - [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")] - //This class is used to communicate option values between components, it does not have any functionality which might modify these values. + /// + [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Justification = "This class is used to communicate option values between components, it does not have any functionality which might modify these values.")] public bool ignoreRegisteredOcx; + /// /// The file containing the strong name key container for the generated assemblies. + /// public string keyContainer = null; + /// /// The file containing the strong name key for the generated assemblies. + /// public string keyFile = null; + /// /// The strong name used for the generated assemblies. + /// public StrongNameKeyPair keyPair = null; + /// /// Flag that controls whether we should output errors in the MSBuild format. + /// public bool msBuildErrors = false; + /// /// Flag that controls whether we should show the logo. + /// public bool noLogo = false; + /// /// The output directory for all the generated assemblies. + /// public string outputDirectory = null; + /// /// The path-included filename of type library containing the definition of the ActiveX control. + /// public string outputName = null; + /// /// The flag that controls whether we try to overwrite existing generated assemblies. + /// public bool overwriteRCW = false; + + /// /// The public key used to sign the generated assemblies. + /// public byte[] publicKey = null; + /// /// The object that allows us to resolve types and references needed to generate assemblies. + /// public IReferenceResolver references = null; + /// /// Flag that controls the output generated. + /// public bool silentMode = false; + /// /// Flag that controls the output generated. + /// public bool verboseMode = false; } /// - /// The Reference Resolver service will try to look through the references it can obtain, - /// for a reference that matches the given criterion. For now, the only kind of references - /// it can look for are COM (RCW) references and ActiveX wrapper references. + /// The Reference Resolver service will try to look through the references it can obtain, + /// for a reference that matches the given criterion. For now, the only kind of references + /// it can look for are COM (RCW) references and ActiveX wrapper references. /// public interface IReferenceResolver { @@ -88,36 +116,3 @@ public interface IReferenceResolver } } } - -namespace System.Runtime.InteropServices -{ - - // UCOMITypeLib is not yet ported to interop on core. - - [Guid("00020402-0000-0000-C000-000000000046")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface UCOMITypeLib - { - [PreserveSig] - int GetTypeInfoCount(); - - //void GetTypeInfo(int index, out UCOMITypeInfo ppTI); - void GetTypeInfoType(int index, out TYPEKIND pTKind); - - //void GetTypeInfoOfGuid(ref Guid guid, out UCOMITypeInfo ppTInfo); - void GetLibAttr(out IntPtr ppTLibAttr); - - //void GetTypeComp(out UCOMITypeComp ppTComp); - void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, - out string strHelpFile); - - [return: MarshalAs(UnmanagedType.Bool)] - bool IsName([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal); - - //void FindName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal, [MarshalAs(UnmanagedType.LPArray), Out] UCOMITypeInfo[] ppTInfo, [MarshalAs(UnmanagedType.LPArray), Out] int[] rgMemId, ref Int16 pcFound); - [PreserveSig] - void ReleaseTLibAttr(IntPtr pTLibAttr); - } - -} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerOptions.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerOptions.cs index 14ed6688dd0..30e06031529 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerOptions.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/DesignerOptions.cs @@ -16,16 +16,8 @@ public class DesignerOptions { private const int MinGridSize = 2; private const int MaxGridSize = 200; - private bool _showGrid = true; - private bool _snapToGrid = true; private Size _gridSize = new Size(8, 8); - private bool _useSnapLines = false; - private bool _useSmartTags = false; - private bool _objectBoundSmartTagAutoShow = true; - private bool _enableComponentCache = false; - private bool _enableInSituEditing = true; - /// /// Public GridSize property. /// @@ -38,10 +30,23 @@ public virtual Size GridSize set { //do some validation checking here - if (value.Width < MinGridSize) value.Width = MinGridSize; - if (value.Height < MinGridSize) value.Height = MinGridSize; - if (value.Width > MaxGridSize) value.Width = MaxGridSize; - if (value.Height > MaxGridSize) value.Height = MaxGridSize; + if (value.Width < MinGridSize) + { + value.Width = MinGridSize; + } + if (value.Height < MinGridSize) + { + value.Height = MinGridSize; + } + if (value.Width > MaxGridSize) + { + value.Width = MaxGridSize; + } + if (value.Height > MaxGridSize) + { + value.Height = MaxGridSize; + } + _gridSize = value; } } @@ -52,11 +57,7 @@ public virtual Size GridSize [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDisplayName(nameof(SR.DesignerOptions_ShowGridDisplayName))] [SRDescription(nameof(SR.DesignerOptions_ShowGridDesc))] - public virtual bool ShowGrid - { - get => _showGrid; - set => _showGrid = value; - } + public virtual bool ShowGrid { get; set; } = true; /// /// Public SnapToGrid property. @@ -64,33 +65,21 @@ public virtual bool ShowGrid [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDisplayName(nameof(SR.DesignerOptions_SnapToGridDisplayName))] [SRDescription(nameof(SR.DesignerOptions_SnapToGridDesc))] - public virtual bool SnapToGrid - { - get => _snapToGrid; - set => _snapToGrid = value; - } + public virtual bool SnapToGrid { get; set; } = true; /// /// This property enables or disables snaplines in the designer. /// [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDescription(nameof(SR.DesignerOptions_UseSnapLines))] - public virtual bool UseSnapLines - { - get => _useSnapLines; - set => _useSnapLines = value; - } + public virtual bool UseSnapLines { get; set; } /// /// This property enables or disables smart tags in the designer. /// [SRCategory(nameof(SR.DesignerOptions_LayoutSettings))] [SRDescription(nameof(SR.DesignerOptions_UseSmartTags))] - public virtual bool UseSmartTags - { - get => _useSmartTags; - set => _useSmartTags = value; - } + public virtual bool UseSmartTags { get; set; } /// /// This property enables or disables smart tags in the designer. @@ -98,11 +87,7 @@ public virtual bool UseSmartTags [SRDisplayName(nameof(SR.DesignerOptions_ObjectBoundSmartTagAutoShowDisplayName))] [SRCategory(nameof(SR.DesignerOptions_ObjectBoundSmartTagSettings))] [SRDescription(nameof(SR.DesignerOptions_ObjectBoundSmartTagAutoShow))] - public virtual bool ObjectBoundSmartTagAutoShow - { - get => _objectBoundSmartTagAutoShow; - set => _objectBoundSmartTagAutoShow = value; - } + public virtual bool ObjectBoundSmartTagAutoShow { get; set; } = true; /// /// This property enables or disables the component cache @@ -110,11 +95,7 @@ public virtual bool ObjectBoundSmartTagAutoShow [SRDisplayName(nameof(SR.DesignerOptions_CodeGenDisplay))] [SRCategory(nameof(SR.DesignerOptions_CodeGenSettings))] [SRDescription(nameof(SR.DesignerOptions_OptimizedCodeGen))] - public virtual bool UseOptimizedCodeGeneration - { - get => _enableComponentCache; - set => _enableComponentCache = value; - } + public virtual bool UseOptimizedCodeGeneration { get; set; } /// /// This property enables or disables the InSitu Editing for ToolStrips @@ -123,10 +104,6 @@ public virtual bool UseOptimizedCodeGeneration [SRCategory(nameof(SR.DesignerOptions_EnableInSituEditingCat))] [SRDescription(nameof(SR.DesignerOptions_EnableInSituEditingDesc))] [Browsable(false)] - public virtual bool EnableInSituEditing - { - get => _enableInSituEditing; - set => _enableInSituEditing = value; - } + public virtual bool EnableInSituEditing { get; set; } = true; } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MenuCommands.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MenuCommands.cs index 42667652b5a..cb14f082788 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MenuCommands.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/MenuCommands.cs @@ -7,27 +7,20 @@ namespace System.Windows.Forms.Design { /// - /// - /// This class contains command ID's and GUIDS that - /// correspond - /// to the host Command Bar menu layout. - /// + /// This class contains command ID's and GUIDS that correspond to the host Command Bar menu layout. /// public sealed class MenuCommands : StandardCommands { // Windows Forms specific popup menus - // private const int mnuidSelection = 0x0500; private const int mnuidContainer = 0x0501; private const int mnuidTraySelection = 0x0503; private const int mnuidComponentTray = 0x0506; // Windows Forms specific menu items - // private const int cmdidDesignerProperties = 0x1001; // Windows Forms specific keyboard commands - // private const int cmdidReverseCancel = 0x4001; private const int cmdidSetStatusText = 0x4003; private const int cmdidSetStatusRectangle = 0x4004; @@ -65,26 +58,26 @@ public sealed class MenuCommands : StandardCommands private const int ECMD_END_EXT = 18; /// - /// This guid corresponds to the standard set of commands for the shell and office. - /// This new giud is added so that the ToolStripDesigner now respond to the F2 command - /// and go into InSitu Edit mode. + /// This guid corresponds to the standard set of commands for the shell and office. + /// This new giud is added so that the ToolStripDesigner now respond to the F2 command + /// and go into InSitu Edit mode. /// private static readonly Guid VSStandardCommandSet97 = new Guid("{5efc7975-14bc-11cf-9b2b-00aa00573819}"); /// - /// This guid corresponds to the menu grouping Windows Forms will use for its menus. This is - /// defined in the Windows Forms menu CTC file, but we need it here so we can define what - /// context menus to use. + /// This guid corresponds to the menu grouping Windows Forms will use for its menus. This is + /// defined in the Windows Forms menu CTC file, but we need it here so we can define what + /// context menus to use. /// private static readonly Guid wfMenuGroup = new Guid("{74D21312-2AEE-11d1-8BFB-00A0C90F26F7}"); /// - /// This guid corresponds to the Windows Forms command set. + /// This guid corresponds to the Windows Forms command set. /// private static readonly Guid wfCommandSet = new Guid("{74D21313-2AEE-11d1-8BFB-00A0C90F26F7}"); /// - /// This guid is the standard vs 2k commands for key bindings + /// This guid is the standard vs 2k commands for key bindings /// private static readonly Guid guidVSStd2K = new Guid("{1496A755-94DE-11D0-8C3F-00C04FC2AAE2}"); @@ -97,11 +90,9 @@ public sealed class MenuCommands : StandardCommands public static readonly CommandID ComponentTrayMenu = new CommandID(wfMenuGroup, mnuidComponentTray); // Windows Forms commands - public static readonly CommandID DesignerProperties = new CommandID(wfCommandSet, cmdidDesignerProperties); - // Windows Forms Key commands - + // Windows Forms Key commands public static readonly CommandID KeyCancel = new CommandID(guidVSStd2K, ECMD_CANCEL); public static readonly CommandID KeyReverseCancel = new CommandID(wfCommandSet, cmdidReverseCancel); diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardGroups.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardGroups.cs index 90e48fcb4f1..28a32108b81 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardGroups.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/StandardGroups.cs @@ -2,12 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics.CodeAnalysis; - namespace System.Windows.Forms.Design { - [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] - internal class StandardGroups + internal static class StandardGroups { public const string Code = "Code"; public const string ZORder = "ZOrder"; diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarMode.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarMode.cs index 0db15f48949..af40c680ac9 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarMode.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarMode.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections; - namespace System.Windows.Forms.Design { public enum ThemedScrollbarMode @@ -23,10 +21,4 @@ public enum ThemedScrollbarMode /// OnlyTopLevel = 3 }; - - public struct ThemedScrollbarWindow - { - public IntPtr Handle; - public ThemedScrollbarMode Mode; - } } diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarWindow.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarWindow.cs new file mode 100644 index 00000000000..24a3fcf8ebf --- /dev/null +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ThemedScrollbarWindow.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Forms.Design +{ + public struct ThemedScrollbarWindow + { + public IntPtr Handle; + public ThemedScrollbarMode Mode; + } +} diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs index 548a2b526c3..4ba6af0d4c8 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs @@ -7,27 +7,17 @@ namespace System.Windows.Forms.Design { /// - /// Makes the DesignerOptions queryable through the IDesignerOption service. + /// Makes the DesignerOptions queryable through the IDesignerOption service. /// public class WindowsFormsDesignerOptionService : DesignerOptionService { private DesignerOptions _options; - public virtual DesignerOptions CompatibilityOptions - { - get - { - if (_options == null) - { - _options = new DesignerOptions(); - } - return _options; - } - } + public virtual DesignerOptions CompatibilityOptions => _options ?? (_options = new DesignerOptions()); /// - /// This method is called on demand the first time a user asks for child - /// options or properties of an options collection. + /// This method is called on demand the first time a user asks for child options or properties of an + /// options collection. /// protected override void PopulateOptionCollection(DesignerOptionCollection options) { From b1149d383da3cb94f06381cf68ac297136f6e890 Mon Sep 17 00:00:00 2001 From: Hugh Bellamy Date: Tue, 16 Apr 2019 17:53:10 +0100 Subject: [PATCH 2/3] Add misc Design tests and fix a NullRef bug --- .../WindowsFormsDesignerOptionService.cs | 2 +- .../Forms/Design/DesignerOptionsTests.cs | 187 ++++++++++++++++++ .../Windows/Forms/Design/MenuCommandsTests.cs | 67 +++++++ .../WindowsFormsDesignerOptionServiceTests.cs | 78 ++++++++ 4 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/DesignerOptionsTests.cs create mode 100644 src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MenuCommandsTests.cs create mode 100644 src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs index 4ba6af0d4c8..4190b9bd8d4 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs @@ -21,7 +21,7 @@ public class WindowsFormsDesignerOptionService : DesignerOptionService /// protected override void PopulateOptionCollection(DesignerOptionCollection options) { - if (options.Parent == null) + if (options?.Parent == null) { DesignerOptions designerOptions = CompatibilityOptions; if (designerOptions != null) diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/DesignerOptionsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/DesignerOptionsTests.cs new file mode 100644 index 00000000000..e12708de140 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/DesignerOptionsTests.cs @@ -0,0 +1,187 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Drawing; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Windows.Forms.Design.Tests +{ + public class DesignerOptionsTests + { + [Fact] + public void DesignerOptions_Ctor_Default() + { + var options = new DesignerOptions(); + Assert.True(options.EnableInSituEditing); + Assert.Equal(new Size(8, 8), options.GridSize); + Assert.True(options.ObjectBoundSmartTagAutoShow); + Assert.True(options.ShowGrid); + Assert.True(options.SnapToGrid); + Assert.False(options.UseOptimizedCodeGeneration); + Assert.False(options.UseSmartTags); + Assert.False(options.UseSnapLines); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_EnableInSituEditing_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + EnableInSituEditing = value + }; + Assert.Equal(value, options.EnableInSituEditing); + + // Set same. + options.EnableInSituEditing = value; + Assert.Equal(value, options.EnableInSituEditing); + + // Set different. + options.EnableInSituEditing = !value; + Assert.Equal(!value, options.EnableInSituEditing); + } + + public static IEnumerable GridSize_Set_TestData() + { + yield return new object[] { new Size(0, 0), new Size(2, 2) }; + yield return new object[] { new Size(0, 2), new Size(2, 2) }; + yield return new object[] { new Size(2, 0), new Size(2, 2) }; + yield return new object[] { new Size(2, 2), new Size(2, 2) }; + yield return new object[] { new Size(200, 200), new Size(200, 200) }; + yield return new object[] { new Size(201, 200), new Size(200, 200) }; + yield return new object[] { new Size(200, 201), new Size(200, 200) }; + } + + [Theory] + [MemberData(nameof(GridSize_Set_TestData))] + public void DesignerOptions_GridSize_Set_GetReturnsExpected(Size value, Size expected) + { + var options = new DesignerOptions + { + GridSize = value + }; + Assert.Equal(expected, options.GridSize); + + // Set same. + options.GridSize = value; + Assert.Equal(expected, options.GridSize); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_ObjectBoundSmartTagAutoShow_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + ObjectBoundSmartTagAutoShow = value + }; + Assert.Equal(value, options.ObjectBoundSmartTagAutoShow); + + // Set same. + options.ObjectBoundSmartTagAutoShow = value; + Assert.Equal(value, options.ObjectBoundSmartTagAutoShow); + + // Set different. + options.ObjectBoundSmartTagAutoShow = !value; + Assert.Equal(!value, options.ObjectBoundSmartTagAutoShow); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_ShowGrid_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + ShowGrid = value + }; + Assert.Equal(value, options.ShowGrid); + + // Set same. + options.ShowGrid = value; + Assert.Equal(value, options.ShowGrid); + + // Set different. + options.ShowGrid = !value; + Assert.Equal(!value, options.ShowGrid); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_SnapToGrid_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + SnapToGrid = value + }; + Assert.Equal(value, options.SnapToGrid); + + // Set same. + options.SnapToGrid = value; + Assert.Equal(value, options.SnapToGrid); + + // Set different. + options.SnapToGrid = !value; + Assert.Equal(!value, options.SnapToGrid); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_UseOptimizedCodeGeneration_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + UseOptimizedCodeGeneration = value + }; + Assert.Equal(value, options.UseOptimizedCodeGeneration); + + // Set same. + options.UseOptimizedCodeGeneration = value; + Assert.Equal(value, options.UseOptimizedCodeGeneration); + + // Set different. + options.UseOptimizedCodeGeneration = !value; + Assert.Equal(!value, options.UseOptimizedCodeGeneration); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_UseSmartTags_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + UseSmartTags = value + }; + Assert.Equal(value, options.UseSmartTags); + + // Set same. + options.UseSmartTags = value; + Assert.Equal(value, options.UseSmartTags); + + // Set different. + options.UseSmartTags = !value; + Assert.Equal(!value, options.UseSmartTags); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void DesignerOptions_UseSnapLines_Set_GetReturnsExpected(bool value) + { + var options = new DesignerOptions + { + UseSnapLines = value + }; + Assert.Equal(value, options.UseSnapLines); + + // Set same. + options.UseSnapLines = value; + Assert.Equal(value, options.UseSnapLines); + + // Set different. + options.UseSnapLines = !value; + Assert.Equal(!value, options.UseSnapLines); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MenuCommandsTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MenuCommandsTests.cs new file mode 100644 index 00000000000..a24ce0401f5 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/MenuCommandsTests.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.ComponentModel.Design; +using Xunit; + +namespace System.Windows.Forms.Design.Tests +{ + public class MenuCommandsTests + { + [Fact] + public void MenuCommands_Ctor_Default() + { + // Make sure it doesn't throw. + new MenuCommands(); + } + + public static IEnumerable Commands_TestData() + { + yield return new object[] { MenuCommands.ComponentTrayMenu, new CommandID(new Guid("74d21312-2aee-11d1-8bfb-00a0c90f26f7"), 1286) }; + yield return new object[] { MenuCommands.ContainerMenu, new CommandID(new Guid("74d21312-2aee-11d1-8bfb-00a0c90f26f7"), 1281) }; + yield return new object[] { MenuCommands.DesignerProperties, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 4097) }; + yield return new object[] { MenuCommands.EditLabel, new CommandID(new Guid("5efc7975-14bc-11cf-9b2b-00aa00573819"), 338) }; + yield return new object[] { MenuCommands.KeyCancel, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 103) }; + yield return new object[] { MenuCommands.KeyDefaultAction, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 3) }; + yield return new object[] { MenuCommands.KeyEnd, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 17) }; + yield return new object[] { MenuCommands.KeyHome, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 15) }; + yield return new object[] { MenuCommands.KeyInvokeSmartTag, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 147) }; + yield return new object[] { MenuCommands.KeyMoveDown, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 13) }; + yield return new object[] { MenuCommands.KeyMoveLeft, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 7) }; + yield return new object[] { MenuCommands.KeyMoveRight, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 9) }; + yield return new object[] { MenuCommands.KeyMoveUp, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 11) }; + yield return new object[] { MenuCommands.KeyNudgeDown, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1225) }; + yield return new object[] { MenuCommands.KeyNudgeHeightDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1229) }; + yield return new object[] { MenuCommands.KeyNudgeHeightIncrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1228) }; + yield return new object[] { MenuCommands.KeyNudgeLeft, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1224) }; + yield return new object[] { MenuCommands.KeyNudgeRight, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1226) }; + yield return new object[] { MenuCommands.KeyNudgeUp, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1227) }; + yield return new object[] { MenuCommands.KeyNudgeWidthDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1230) }; + yield return new object[] { MenuCommands.KeyNudgeWidthDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1230) }; + yield return new object[] { MenuCommands.KeyNudgeHeightIncrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 1228) }; + yield return new object[] { MenuCommands.KeyReverseCancel, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 16385) }; + yield return new object[] { MenuCommands.KeySelectNext, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 4) }; + yield return new object[] { MenuCommands.KeySelectPrevious, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 5) }; + yield return new object[] { MenuCommands.KeyShiftEnd, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 18) }; + yield return new object[] { MenuCommands.KeyShiftHome, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 16) }; + yield return new object[] { MenuCommands.KeySizeHeightDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 14) }; + yield return new object[] { MenuCommands.KeySizeHeightIncrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 12) }; + yield return new object[] { MenuCommands.KeySizeWidthDecrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 8) }; + yield return new object[] { MenuCommands.KeySizeWidthIncrease, new CommandID(new Guid("1496a755-94de-11d0-8c3f-00c04fc2aae2"), 10) }; + yield return new object[] { MenuCommands.KeyTabOrderSelect, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 16405) }; + yield return new object[] { MenuCommands.SelectionMenu, new CommandID(new Guid("74d21312-2aee-11d1-8bfb-00a0c90f26f7"), 1280) }; + yield return new object[] { MenuCommands.SetStatusRectangle, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 16388) }; + yield return new object[] { MenuCommands.SetStatusText, new CommandID(new Guid("74d21313-2aee-11d1-8bfb-00a0c90f26f7"), 16387) }; + yield return new object[] { MenuCommands.TraySelectionMenu, new CommandID(new Guid("74d21312-2aee-11d1-8bfb-00a0c90f26f7"), 1283) }; + } + + [Theory] + [MemberData(nameof(Commands_TestData))] + public void MenuCommands_Commands_Get_ReturnsExected(CommandID command, CommandID expected) + { + Assert.Equal(expected, command); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs new file mode 100644 index 00000000000..bd46e65a0c7 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.Linq; +using Xunit; + +namespace System.Windows.Forms.Design.Tests +{ + public class WindowsFormsDesignerOptionServiceTests + { + [Fact] + public void WindowsFormsDesignerOptionService_Ctor_Default() + { + var service = new WindowsFormsDesignerOptionService(); + DesignerOptions options = service.CompatibilityOptions; + Assert.True(options.EnableInSituEditing); + Assert.Equal(new Size(8, 8), options.GridSize); + Assert.True(options.ObjectBoundSmartTagAutoShow); + Assert.True(options.ShowGrid); + Assert.True(options.SnapToGrid); + Assert.False(options.UseSmartTags); + Assert.False(options.UseSnapLines); + Assert.False(options.UseOptimizedCodeGeneration); + Assert.Same(options, service.CompatibilityOptions); + } + + [Fact] + public void WindowsFormsDesignerOptionService_Options_Get_ReturnsExpected() + { + var service = new WindowsFormsDesignerOptionService(); + Assert.Empty(service.Options.Name); + DesignerOptionService.DesignerOptionCollection childCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal("DesignerOptions", childCollection.Name); + Assert.Same(service.Options, childCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(childCollection); + } + + [Fact] + public void WindowsFormsDesignerOptionService_Options_GetNullDesignerOptions_ReturnsExpected() + { + var service = new NullCompatibilityOptions(); + Assert.Empty(service.Options.Name); + Assert.Empty(service.Options); + } + + [Fact] + public void WindowsFormsDesignerOptionService_PopulateOptionCollection_ValidOptions_Success() + { + var service = new SubWindowsFormsDesignerOptionService(); + var otherService = new SubWindowsFormsDesignerOptionService(); + service.PopulateOptionCollection(otherService.Options); + Assert.Empty(service.Options); + Assert.Empty(otherService.Options); + } + + [Fact] + public void WindowsFormsDesignerOptionService_PopulateOptionCollection_NullOptions_Success() + { + var service = new SubWindowsFormsDesignerOptionService(); + service.PopulateOptionCollection(null); + } + + private class SubWindowsFormsDesignerOptionService : DesignerOptionService + { + public new void PopulateOptionCollection(DesignerOptionCollection options) => base.PopulateOptionCollection(options); + } + + private class NullCompatibilityOptions : WindowsFormsDesignerOptionService + { + public override DesignerOptions CompatibilityOptions => null; + } + } +} From c268efcda5a21caa64b0363b98e54ede355ac97e Mon Sep 17 00:00:00 2001 From: Hugh Bellamy Date: Tue, 16 Apr 2019 23:55:06 +0100 Subject: [PATCH 3/3] Fix oversight in tests/code --- .../WindowsFormsDesignerOptionService.cs | 18 ++--- .../WindowsFormsDesignerOptionServiceTests.cs | 65 +++++++++++++++++-- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs index 4190b9bd8d4..c44cada0915 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/WindowsFormsDesignerOptionService.cs @@ -16,18 +16,20 @@ public class WindowsFormsDesignerOptionService : DesignerOptionService public virtual DesignerOptions CompatibilityOptions => _options ?? (_options = new DesignerOptions()); /// - /// This method is called on demand the first time a user asks for child options or properties of an - /// options collection. + /// This method is called on demand the first time a user asks for child options or + /// properties of an options collection. /// protected override void PopulateOptionCollection(DesignerOptionCollection options) { - if (options?.Parent == null) + if (options == null || options.Parent != null) { - DesignerOptions designerOptions = CompatibilityOptions; - if (designerOptions != null) - { - CreateOptionCollection(options, "DesignerOptions", designerOptions); - } + return; + } + + DesignerOptions designerOptions = CompatibilityOptions; + if (designerOptions != null) + { + CreateOptionCollection(options, "DesignerOptions", designerOptions); } } } diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs index bd46e65a0c7..2de5130c1b7 100644 --- a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/WindowsFormsDesignerOptionServiceTests.cs @@ -49,25 +49,76 @@ public void WindowsFormsDesignerOptionService_Options_GetNullDesignerOptions_Ret } [Fact] - public void WindowsFormsDesignerOptionService_PopulateOptionCollection_ValidOptions_Success() + public void WindowsFormsDesignerOptionService_PopulateOptionCollection_ValidOptionsFromSameClass_Success() + { + var service = new SubWindowsFormsDesignerOptionService(); + service.PopulateOptionCollectionEntry(service.Options); + Assert.Equal(1, service.PopulateOptionCollectionCallCount); + + // Should not retrieve again when accessing Options. + DesignerOptionService.DesignerOptionCollection childCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal(1, service.PopulateOptionCollectionCallCount); + Assert.Equal("DesignerOptions", childCollection.Name); + Assert.Same(service.Options, childCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(childCollection); + } + + [Fact] + public void WindowsFormsDesignerOptionService_PopulateOptionCollection_ValidOptionsFromOtherClass_Success() { var service = new SubWindowsFormsDesignerOptionService(); var otherService = new SubWindowsFormsDesignerOptionService(); - service.PopulateOptionCollection(otherService.Options); - Assert.Empty(service.Options); - Assert.Empty(otherService.Options); + service.PopulateOptionCollectionEntry(otherService.Options); + Assert.Equal(1, service.PopulateOptionCollectionCallCount); + + // Should retrieve again when accessing Options. + DesignerOptionService.DesignerOptionCollection childCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal(2, service.PopulateOptionCollectionCallCount); + Assert.Equal("DesignerOptions", childCollection.Name); + Assert.Same(service.Options, childCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(childCollection); + + DesignerOptionService.DesignerOptionCollection otherChildCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal(0, otherService.PopulateOptionCollectionCallCount); + Assert.Equal("DesignerOptions", otherChildCollection.Name); + Assert.Same(service.Options, otherChildCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(otherChildCollection); } [Fact] public void WindowsFormsDesignerOptionService_PopulateOptionCollection_NullOptions_Success() { var service = new SubWindowsFormsDesignerOptionService(); - service.PopulateOptionCollection(null); + service.PopulateOptionCollectionEntry(null); + Assert.Equal(1, service.PopulateOptionCollectionCallCount); + + // Should retrieve again when accessing Options. + DesignerOptionService.DesignerOptionCollection childCollection = Assert.IsType(Assert.Single(service.Options)); + Assert.Equal(2, service.PopulateOptionCollectionCallCount); + Assert.Equal("DesignerOptions", childCollection.Name); + Assert.Same(service.Options, childCollection.Parent); + Assert.Equal(new string[] { "EnableInSituEditing", "GridSize", "ObjectBoundSmartTagAutoShow", "ShowGrid", "SnapToGrid", "UseOptimizedCodeGeneration", "UseSmartTags", "UseSnapLines" }, childCollection.Properties.Sort().Cast().Select(p => p.Name)); + Assert.Empty(childCollection); + Assert.Equal(3, service.PopulateOptionCollectionCallCount); } - private class SubWindowsFormsDesignerOptionService : DesignerOptionService + private class SubWindowsFormsDesignerOptionService : WindowsFormsDesignerOptionService { - public new void PopulateOptionCollection(DesignerOptionCollection options) => base.PopulateOptionCollection(options); + public int PopulateOptionCollectionCallCount { get; set; } + + public void PopulateOptionCollectionEntry(DesignerOptionCollection options) + { + PopulateOptionCollection(options); + } + + protected override void PopulateOptionCollection(DesignerOptionCollection options) + { + PopulateOptionCollectionCallCount++; + base.PopulateOptionCollection(options); + } } private class NullCompatibilityOptions : WindowsFormsDesignerOptionService