diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonForm.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonForm.cs index bd677571ca..ecfc0a4198 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonForm.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonForm.cs @@ -207,6 +207,9 @@ namespace ICSharpCode.PythonBinding return null; } + /// + /// Checks whether the method is marked with the DesignerSerializationVisibility.Hidden attribute. + /// public static bool IsHiddenFromDesignerSerializer(MethodInfo methodInfo) { foreach (DesignerSerializationVisibilityAttribute attribute in methodInfo.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true)) { @@ -217,6 +220,29 @@ namespace ICSharpCode.PythonBinding return false; } + /// + /// Gets the child components that are sited on the specified object. + /// + /// + /// For a MenuStrip the child components include the MenuStrip.Items. + /// For a Control the child components include the Control.Controls. + /// + public static IComponent[] GetChildComponents(object obj) + { + List childComponents = new List(); + foreach (PropertyDescriptor property in GetSerializableContentProperties(obj)) { + ICollection collection = property.GetValue(obj) as ICollection; + if (collection != null) { + foreach (object component in collection) { + if (IsSitedComponent(component)) { + childComponents.Add(component as IComponent); + } + } + } + } + return childComponents.ToArray(); + } + void GenerateInitializeComponentMethodBodyInternal(Form form) { AppendChildControlCreation(form); @@ -235,36 +261,31 @@ namespace ICSharpCode.PythonBinding { // Add the controls on the form. foreach (Control control in form.Controls) { - AppendControl(control); + AppendComponent(control); } // Add form. - AppendControl(form, false, false); + AppendComponent(form, false, false); } - void AppendControl(Control control) + void AppendComponent(IComponent component) { - AppendControl(control, true, true); + AppendComponent(component, true, true); } /// - /// Generates python code for the control. + /// Generates python code for the component. /// - void AppendControl(Control control, bool addControlNameToProperty, bool addChildControlProperties) + void AppendComponent(IComponent component, bool addComponentNameToProperty, bool addChildComponentProperties) { - AppendComment(control.Name); + AppendComment(component.Site.Name); - string propertyOwnerName = GetPropertyOwnerName(control, addControlNameToProperty); - AppendProperties(propertyOwnerName, control); - AppendEventHandlers(propertyOwnerName, control); - - MenuStrip menuStrip = control as MenuStrip; - if (menuStrip != null) { - AppendToolStripItems(menuStrip.Items); - } + string propertyOwnerName = GetPropertyOwnerName(component, addComponentNameToProperty); + AppendProperties(propertyOwnerName, component); + AppendEventHandlers(propertyOwnerName, component); - if (addChildControlProperties) { - AppendChildControlProperties(control.Controls); + if (addChildComponentProperties) { + AppendChildComponentProperties(component); } } @@ -348,45 +369,23 @@ namespace ICSharpCode.PythonBinding void AppendChildControlCreation(Control parentControl) { - MenuStrip menuStrip = parentControl as MenuStrip; - if (menuStrip != null) { - AppendChildControlCreation(menuStrip.Items); - } else { - AppendChildControlCreation(parentControl.Controls); - } - } - - void AppendChildControlCreation(Control.ControlCollection controls) - { - foreach (Control control in controls) { - if (IsSitedComponent(control)) { - AppendComponentCreation(control); - AppendChildControlCreation(control); - } - } + AppendChildComponentCreation(GetChildComponents(parentControl)); } - - void AppendChildControlCreation(ToolStripItemCollection toolStripItems) + + void AppendChildComponentCreation(ICollection components) { - foreach (ToolStripItem item in toolStripItems) { - if (IsSitedComponent(item)) { - AppendComponentCreation(item); - } - ToolStripMenuItem menuItem = item as ToolStripMenuItem; - if (menuItem != null) { - AppendChildControlCreation(menuItem.DropDownItems); + foreach (object obj in components) { + IComponent component = obj as IComponent; + if (IsSitedComponent(component)) { + AppendComponentCreation(component); + AppendChildComponentCreation(GetChildComponents(component)); } } } - void AppendComponentCreation(Control control) + void AppendComponentCreation(IComponent component) { - AppendComponentCreation(control.Name, control); - } - - void AppendComponentCreation(ToolStripItem item) - { - AppendComponentCreation(item.Name, item); + AppendComponentCreation(component.Site.Name, component); } void AppendComponentCreation(string name, object obj) @@ -424,47 +423,34 @@ namespace ICSharpCode.PythonBinding /// enumerator is called first. Sorting will only occur if an item is retrieved after calling /// Sort or CopyTo is called. The PropertyDescriptorCollection class does not behave /// in the same way. - void AppendEventHandlers(string propertyOwnerName, Control control) + void AppendEventHandlers(string propertyOwnerName, object component) { - EventDescriptorCollection events = TypeDescriptor.GetEvents(control, notDesignOnlyFilter).Sort(); + EventDescriptorCollection events = TypeDescriptor.GetEvents(component, notDesignOnlyFilter).Sort(); if (events.Count > 0) { EventDescriptor dummyEventDescriptor = events[0]; } foreach (EventDescriptor eventDescriptor in events) { - AppendEventHandler(propertyOwnerName, control, eventDescriptor); + AppendEventHandler(propertyOwnerName, component, eventDescriptor); } } - void AppendEventHandler(string propertyOwnerName, Control control, EventDescriptor eventDescriptor) + void AppendEventHandler(string propertyOwnerName, object component, EventDescriptor eventDescriptor) { PropertyDescriptor propertyDescriptor = eventBindingService.GetEventProperty(eventDescriptor); - if (propertyDescriptor.ShouldSerializeValue(control)) { - string methodName = (string)propertyDescriptor.GetValue(control); + if (propertyDescriptor.ShouldSerializeValue(component)) { + string methodName = (string)propertyDescriptor.GetValue(component); AppendIndentedLine(GetPropertyName(propertyOwnerName, eventDescriptor.Name) + " += self." + methodName); } } bool HasSitedChildComponents(Control control) { - MenuStrip menuStrip = control as MenuStrip; - if (menuStrip != null) { - return HasSitedComponents(menuStrip.Items); - } - - if (control.Controls.Count > 0) { - foreach (Control childControl in control.Controls) { - if (!IsSitedComponent(childControl)) { - return false; - } - } - return true; - } - return false; + return HasSitedComponents(GetChildComponents(control)); } - bool HasSitedComponents(ToolStripItemCollection items) + bool HasSitedComponents(ICollection items) { - foreach (ToolStripItem item in items) { + foreach (object item in items) { if (IsSitedComponent(item)) { return true; } @@ -497,39 +483,7 @@ namespace ICSharpCode.PythonBinding AppendLine(); DecreaseIndent(); } - } - - List GetSitedToolStripItems(ToolStripItemCollection items) - { - List sitedItems = new List(); - foreach (ToolStripItem item in items) { - if (IsSitedComponent(item)) { - sitedItems.Add(item); - } - } - return sitedItems; - } - - void AppendToolStripItems(IList items) - { - foreach (ToolStripItem item in items) { - if (IsSitedComponent(item)) { - AppendToolStripItem(item); - } - } - } - - void AppendToolStripItem(ToolStripItem item) - { - AppendComment(item.Name); - AppendProperties(item.Name, item); - - ToolStripMenuItem menuItem = item as ToolStripMenuItem; - if (menuItem != null) { - List sitedItems = GetSitedToolStripItems(menuItem.DropDownItems); - AppendToolStripItems(sitedItems); - } - } + } void AppendProperties(string propertyOwnerName, object obj) { @@ -537,22 +491,32 @@ namespace ICSharpCode.PythonBinding AppendProperty(propertyOwnerName, obj, property); } } - - string GetPropertyOwnerName(Control control, bool addControlNameToProperty) + + string GetPropertyOwnerName(IComponent component, bool addComponentNameToProperty) { - if (addControlNameToProperty) { - return control.Name; + if (addComponentNameToProperty) { + return component.Site.Name; } return String.Empty; } - void AppendChildControlProperties(Control.ControlCollection controls) - { - foreach (Control childControl in controls) { - if (IsSitedComponent(childControl)) { - AppendControl(childControl, true, true); + /// + /// Appends the properties of any component that is contained in a collection property that is + /// marked as DesignerSerializationVisibility.Content. + /// + void AppendChildComponentProperties(object component) + { + foreach (PropertyDescriptor property in PythonForm.GetSerializableContentProperties(component)) { + object propertyCollection = property.GetValue(component); + ICollection collection = propertyCollection as ICollection; + if (collection != null) { + foreach (object childComponent in collection) { + if (IsSitedComponent(childComponent)) { + AppendComponent(childComponent as IComponent , true, true); + } + } } - } + } } /// diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateAcceptButtonFormTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateAcceptButtonFormTestFixture.cs index 091d7bf5cf..994a0f2e0e 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateAcceptButtonFormTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateAcceptButtonFormTestFixture.cs @@ -22,6 +22,8 @@ namespace PythonBinding.Tests.Designer public class GenerateAcceptButtonFormTestFixture { string generatedPythonCode; + IComponent[] formChildComponents; + IComponent[] buttonChildComponents; [TestFixtureSetUp] public void SetUpFixture() @@ -48,6 +50,9 @@ namespace PythonBinding.Tests.Designer PythonForm pythonForm = new PythonForm(" "); generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form); + + formChildComponents = PythonForm.GetChildComponents(form); + buttonChildComponents = PythonForm.GetChildComponents(button); } } @@ -77,5 +82,23 @@ namespace PythonBinding.Tests.Designer Assert.AreEqual(expectedCode, generatedPythonCode); } + + [Test] + public void FormHasOneChildComponent() + { + Assert.AreEqual(1, formChildComponents.Length); + } + + [Test] + public void FormChildComponentIsButton() + { + Assert.IsInstanceOfType(typeof(Button), formChildComponents[0]); + } + + [Test] + public void ButtonHasNoChildComponents() + { + Assert.AreEqual(0, buttonChildComponents.Length); + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs index 1cb30fc785..79c84defa1 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs @@ -26,6 +26,8 @@ namespace PythonBinding.Tests.Designer Size openMenuItemSize; Size exitMenuItemSize; Size editMenuItemSize; + IComponent[] menuStripChildComponents; + IComponent[] fileMenuItemChildComponents; [TestFixtureSetUp] public void SetUpFixture() @@ -77,6 +79,9 @@ namespace PythonBinding.Tests.Designer PythonForm pythonForm = new PythonForm(" "); generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form); + + menuStripChildComponents = PythonForm.GetChildComponents(menuStrip); + fileMenuItemChildComponents = PythonForm.GetChildComponents(fileMenuItem); } } @@ -143,6 +148,32 @@ namespace PythonBinding.Tests.Designer Assert.AreEqual(expectedCode, generatedPythonCode); } + [Test] + public void MenuStripHasTwoChildComponents() + { + Assert.AreEqual(2, menuStripChildComponents.Length); + } + + [Test] + public void MenuStripFirstChildIsFileMenuItem() + { + ToolStripMenuItem fileMenuItem = menuStripChildComponents[0] as ToolStripMenuItem; + Assert.AreEqual("&File", fileMenuItem.Text); + } + + [Test] + public void FileMenuItemHasTwoChildComponents() + { + Assert.AreEqual(2, fileMenuItemChildComponents.Length); + } + + [Test] + public void FileMenuItemFirstChildIsOpenFileMenuItem() + { + ToolStripMenuItem openMenuItem = fileMenuItemChildComponents[0] as ToolStripMenuItem; + Assert.AreEqual("&Open", openMenuItem.Text); + } + string SizeToString(Size size) { return PythonPropertyValueAssignment.ToString(size); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratePanelFormTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratePanelFormTestFixture.cs index 98c193d483..37c695d885 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratePanelFormTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratePanelFormTestFixture.cs @@ -58,7 +58,7 @@ namespace PythonBinding.Tests.Designer generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form); } } - + [Test] public void GeneratedCode() { diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateSimpleFormTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateSimpleFormTestFixture.cs index 392b937990..0b95626571 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateSimpleFormTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateSimpleFormTestFixture.cs @@ -6,6 +6,8 @@ // using System; +using System.ComponentModel; +using System.ComponentModel.Design; using System.Drawing; using System.Windows.Forms; using ICSharpCode.PythonBinding; @@ -22,10 +24,15 @@ namespace PythonBinding.Tests.Designer [TestFixtureSetUp] public void SetUpFixture() { - using (Form form = new Form()) { - form.Name = "MainForm"; + using (DesignSurface designSurface = new DesignSurface(typeof(Form))) { + IDesignerHost host = (IDesignerHost)designSurface.GetService(typeof(IDesignerHost)); + Form form = (Form)host.RootComponent; form.ClientSize = new Size(284, 264); + PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(form); + PropertyDescriptor namePropertyDescriptor = descriptors.Find("Name", false); + namePropertyDescriptor.SetValue(form, "MainForm"); + string indentString = " "; PythonForm pythonForm = new PythonForm(indentString); generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form); @@ -42,7 +49,6 @@ namespace PythonBinding.Tests.Designer " # \r\n" + " self.ClientSize = System.Drawing.Size(284, 264)\r\n" + " self.Name = \"MainForm\"\r\n" + - " self.Visible = False\r\n" + " self.ResumeLayout(False)\r\n" + " self.PerformLayout()\r\n"; diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratorMergeFindsInitializeComponentsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratorMergeFindsInitializeComponentsTestFixture.cs index 4b1a0d7e6c..c888b82d66 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratorMergeFindsInitializeComponentsTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratorMergeFindsInitializeComponentsTestFixture.cs @@ -8,6 +8,8 @@ using System; using System.CodeDom; using System.CodeDom.Compiler; +using System.ComponentModel; +using System.ComponentModel.Design; using System.Drawing; using System.IO; using System.Windows.Forms; @@ -49,9 +51,15 @@ namespace PythonBinding.Tests.Designer parseInfo.SetCompilationUnit(parserCompilationUnit); generator.ParseInfoToReturnFromParseFileMethod = parseInfo; - using (Form form = new Form()) { - form.Name = "MainForm"; + using (DesignSurface designSurface = new DesignSurface(typeof(Form))) { + IDesignerHost host = (IDesignerHost)designSurface.GetService(typeof(IDesignerHost)); + Form form = (Form)host.RootComponent; form.ClientSize = new Size(499, 309); + + PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(form); + PropertyDescriptor namePropertyDescriptor = descriptors.Find("Name", false); + namePropertyDescriptor.SetValue(form, "MainForm"); + generator.MergeRootComponentChanges(form); generator.Detach(); } @@ -96,7 +104,6 @@ namespace PythonBinding.Tests.Designer "\t\t# \r\n" + "\t\tself.ClientSize = System.Drawing.Size(499, 309)\r\n" + "\t\tself.Name = \"MainForm\"\r\n" + - "\t\tself.Visible = False\r\n" + "\t\tself.ResumeLayout(False)\r\n" + "\t\tself.PerformLayout()\r\n"; diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/MergeFormTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/MergeFormTestFixture.cs index f123b96924..1c91e47d0d 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/MergeFormTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/MergeFormTestFixture.cs @@ -7,6 +7,8 @@ using System; using System.CodeDom; +using System.ComponentModel; +using System.ComponentModel.Design; using System.Drawing; using System.IO; using System.Windows.Forms; @@ -39,9 +41,14 @@ namespace PythonBinding.Tests.Designer PythonParser parser = new PythonParser(); ICompilationUnit compilationUnit = parser.Parse(new DefaultProjectContent(), @"test.py", document.TextContent); - using (Form form = new Form()) { - form.Name = "MainForm"; + using (DesignSurface designSurface = new DesignSurface(typeof(Form))) { + IDesignerHost host = (IDesignerHost)designSurface.GetService(typeof(IDesignerHost)); + Form form = (Form)host.RootComponent; form.ClientSize = new Size(499, 309); + + PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(form); + PropertyDescriptor namePropertyDescriptor = descriptors.Find("Name", false); + namePropertyDescriptor.SetValue(form, "MainForm"); PythonDesignerGenerator.Merge(form, document, compilationUnit, new MockTextEditorProperties()); } @@ -75,7 +82,6 @@ namespace PythonBinding.Tests.Designer "\t\t# \r\n" + "\t\tself.ClientSize = System.Drawing.Size(499, 309)\r\n" + "\t\tself.Name = \"MainForm\"\r\n" + - "\t\tself.Visible = False\r\n" + "\t\tself.ResumeLayout(False)\r\n" + "\t\tself.PerformLayout()\r\n"; } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NoNewLineAfterInitializeComponentTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NoNewLineAfterInitializeComponentTestFixture.cs index 5e41a0b43c..33296b74b2 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NoNewLineAfterInitializeComponentTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NoNewLineAfterInitializeComponentTestFixture.cs @@ -7,6 +7,8 @@ using System; using System.CodeDom; +using System.ComponentModel; +using System.ComponentModel.Design; using System.Drawing; using System.IO; using System.Windows.Forms; @@ -38,10 +40,15 @@ namespace PythonBinding.Tests.Designer PythonParser parser = new PythonParser(); ICompilationUnit compilationUnit = parser.Parse(new DefaultProjectContent(), @"test.py", document.TextContent); - using (Form form = new Form()) { - form.Name = "MainForm"; + using (DesignSurface designSurface = new DesignSurface(typeof(Form))) { + IDesignerHost host = (IDesignerHost)designSurface.GetService(typeof(IDesignerHost)); + Form form = (Form)host.RootComponent; form.ClientSize = new Size(499, 309); + PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(form); + PropertyDescriptor namePropertyDescriptor = descriptors.Find("Name", false); + namePropertyDescriptor.SetValue(form, "MainForm"); + PythonDesignerGenerator.Merge(form, document, compilationUnit, new MockTextEditorProperties()); } } @@ -63,7 +70,6 @@ namespace PythonBinding.Tests.Designer "\t\t# \r\n" + "\t\tself.ClientSize = System.Drawing.Size(499, 309)\r\n" + "\t\tself.Name = \"MainForm\"\r\n" + - "\t\tself.Visible = False\r\n" + "\t\tself.ResumeLayout(False)\r\n" + "\t\tself.PerformLayout()\r\n"; diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/TextEditorIndentPassedToGeneratorTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/TextEditorIndentPassedToGeneratorTestFixture.cs index ff7bbc5b8e..24215b42a4 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/TextEditorIndentPassedToGeneratorTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/TextEditorIndentPassedToGeneratorTestFixture.cs @@ -7,6 +7,8 @@ using System; using System.CodeDom; +using System.ComponentModel; +using System.ComponentModel.Design; using System.Drawing; using System.IO; using System.Windows.Forms; @@ -47,10 +49,15 @@ namespace PythonBinding.Tests.Designer ICompilationUnit compilationUnit = parser.Parse(new DefaultProjectContent(), @"test.py", document.TextContent); parseInfo.SetCompilationUnit(compilationUnit); - using (Form form = new Form()) { - form.Name = "MainForm"; + using (DesignSurface designSurface = new DesignSurface(typeof(Form))) { + IDesignerHost host = (IDesignerHost)designSurface.GetService(typeof(IDesignerHost)); + Form form = (Form)host.RootComponent; form.ClientSize = new Size(284, 264); + PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(form); + PropertyDescriptor namePropertyDescriptor = descriptors.Find("Name", false); + namePropertyDescriptor.SetValue(form, "MainForm"); + MockTextEditorProperties textEditorProperties = new MockTextEditorProperties(); textEditorProperties.ConvertTabsToSpaces = true; textEditorProperties.IndentationSize = 1; @@ -77,7 +84,6 @@ namespace PythonBinding.Tests.Designer " # \r\n" + " self.ClientSize = System.Drawing.Size(284, 264)\r\n" + " self.Name = \"MainForm\"\r\n" + - " self.Visible = False\r\n" + " self.ResumeLayout(False)\r\n" + " self.PerformLayout()\r\n";