diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeDeserializer.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeDeserializer.cs
index 4b7d43f88e..7709ad2401 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeDeserializer.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeDeserializer.cs
@@ -124,7 +124,7 @@ namespace ICSharpCode.PythonBinding
}
}
}
- return componentCreator.GetComponent(PythonControlFieldExpression.GetVariableName(field.MemberName));
+ return componentCreator.GetInstance(PythonControlFieldExpression.GetVariableName(field.MemberName));
}
Type GetType(PythonControlFieldExpression field)
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonComponentWalker.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonComponentWalker.cs
index 57f26654d4..df76014942 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonComponentWalker.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonComponentWalker.cs
@@ -195,12 +195,25 @@ namespace ICSharpCode.PythonBinding
return SetPropertyValue(GetCurrentComponent(), name, propertyValue);
}
+ ///
+ /// Returns true if the current component has a property with the specified name.
+ ///
+ bool HasPropertyValue(string name)
+ {
+ return GetPropertyDescriptor(GetCurrentComponent(), name) != null;
+ }
+
+ PropertyDescriptor GetPropertyDescriptor(object component, string name)
+ {
+ return TypeDescriptor.GetProperties(component).Find(name, true);
+ }
+
///
/// Sets the value of a property on the component.
///
bool SetPropertyValue(object component, string name, object propertyValue)
{
- PropertyDescriptor property = TypeDescriptor.GetProperties(component).Find(name, true);
+ PropertyDescriptor property = GetPropertyDescriptor(component, name);
if (property != null) {
propertyValue = ConvertPropertyValue(property, propertyValue);
property.SetValue(component, propertyValue);
@@ -232,10 +245,13 @@ namespace ICSharpCode.PythonBinding
///
/// Adds a component to the list of created objects.
///
- void AddComponent(string name, object component)
+ void AddComponent(string name, object obj)
{
- string variableName = PythonControlFieldExpression.GetVariableName(name);
- componentCreator.Add(component as IComponent, variableName);
+ IComponent component = obj as IComponent;
+ if (component != null) {
+ string variableName = PythonControlFieldExpression.GetVariableName(name);
+ componentCreator.Add(component, variableName);
+ }
}
///
@@ -289,7 +305,8 @@ namespace ICSharpCode.PythonBinding
{
MemberExpression memberExpression = node.Target as MemberExpression;
if (memberExpression != null) {
- object instance = CreateInstance(null, node);
+ string name = GetInstanceName(fieldExpression);
+ object instance = CreateInstance(name, node);
if (instance != null) {
if (!SetPropertyValue(fieldExpression.MemberName, instance)) {
AddComponent(fieldExpression.MemberName, instance);
@@ -305,6 +322,18 @@ namespace ICSharpCode.PythonBinding
}
}
+ ///
+ /// Gets the name of the instance. If the name matches a property of the current component being created
+ /// then this method returns null.
+ ///
+ string GetInstanceName(PythonControlFieldExpression fieldExpression)
+ {
+ if (!HasPropertyValue(fieldExpression.MemberName)) {
+ return PythonControlFieldExpression.GetVariableName(fieldExpression.MemberName);
+ }
+ return null;
+ }
+
///
/// Walks a method call. Typical method calls are:
///
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControl.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControl.cs
index 53d8e4b954..abb11a3082 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControl.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControl.cs
@@ -72,10 +72,15 @@ namespace ICSharpCode.PythonBinding
void GenerateInitializeComponentMethodBodyInternal(Control control)
{
- PythonDesignerComponent rootDesignerComponent = PythonDesignerComponentFactory.CreateDesignerRootComponent(control);
+ PythonDesignerRootComponent rootDesignerComponent = PythonDesignerComponentFactory.CreateDesignerRootComponent(control);
+ if (rootDesignerComponent.HasNonVisualChildComponents()) {
+ rootDesignerComponent.AppendCreateComponentsContainer(codeBuilder);
+ rootDesignerComponent.AppendCreateNonVisualComponents(codeBuilder);
+ }
rootDesignerComponent.AppendCreateChildComponents(codeBuilder);
rootDesignerComponent.AppendChildComponentsSuspendLayout(codeBuilder);
rootDesignerComponent.AppendSuspendLayout(codeBuilder);
+ rootDesignerComponent.AppendNonVisualComponents(codeBuilder);
rootDesignerComponent.AppendComponent(codeBuilder);
rootDesignerComponent.AppendChildComponentsResumeLayout(codeBuilder);
rootDesignerComponent.AppendResumeLayout(codeBuilder);
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs
index 507e4b1fb7..eea0f5fbc1 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs
@@ -122,7 +122,34 @@ namespace ICSharpCode.PythonBinding
}
}
return false;
- }
+ }
+
+ ///
+ /// Returns true if the component has the DesignTimeVisible attribute set to false.
+ ///
+ public static bool IsHiddenFromDesigner(IComponent component)
+ {
+ foreach (DesignTimeVisibleAttribute attribute in component.GetType().GetCustomAttributes(typeof(DesignTimeVisibleAttribute), true)) {
+ return !attribute.Visible;
+ }
+ return false;
+ }
+
+ ///
+ /// A component is non-visual if it is not a control and is not hidden from the designer.
+ ///
+ public static bool IsNonVisualComponent(IComponent component)
+ {
+ Control control = component as Control;
+ return (control == null) && !IsHiddenFromDesigner(component);
+ }
+
+ ///
+ /// Returns true if this component is non-visual.
+ ///
+ public bool IsNonVisual {
+ get { return IsNonVisualComponent(component); }
+ }
///
/// Gets the AddRange method on the object that is not hidden from the designer.
@@ -188,6 +215,11 @@ namespace ICSharpCode.PythonBinding
AppendComponentCreation(codeBuilder, component);
}
+ public void AppendCreateInstance(PythonCodeBuilder codeBuilder, string parameters)
+ {
+ AppendComponentCreation(codeBuilder, component, parameters);
+ }
+
///
/// Appends the code to create the child components.
///
@@ -294,12 +326,11 @@ namespace ICSharpCode.PythonBinding
designerComponent.AppendChildComponentsMethodCalls(codeBuilder, methods);
}
}
-
-
+
///
/// Appends the code to create the specified object.
///
- public void AppendObjectCreation(PythonCodeBuilder codeBuilder, object obj, int count, object[] parameters)
+ public void AppendCreateInstance(PythonCodeBuilder codeBuilder, object obj, int count, object[] parameters)
{
if (obj is String) {
// Do nothing.
@@ -330,9 +361,17 @@ namespace ICSharpCode.PythonBinding
///
public void AppendComponentCreation(PythonCodeBuilder codeBuilder, IComponent component)
{
- codeBuilder.AppendIndentedLine("self._" + component.Site.Name + " = " + component.GetType().FullName + "()");
+ AppendComponentCreation(codeBuilder, component, String.Empty);
}
-
+
+ ///
+ /// Appends the code to create the specified IComponent
+ ///
+ public void AppendComponentCreation(PythonCodeBuilder codeBuilder, IComponent component, string parameters)
+ {
+ codeBuilder.AppendIndentedLine("self._" + component.Site.Name + " = " + component.GetType().FullName + "(" + parameters + ")");
+ }
+
///
/// Generates the code for the component's properties.
///
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponentFactory.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponentFactory.cs
index 40d6cf5de5..deaf032599 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponentFactory.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponentFactory.cs
@@ -28,7 +28,7 @@ namespace ICSharpCode.PythonBinding
return new PythonDesignerComponent(component);
}
- public static PythonDesignerComponent CreateDesignerRootComponent(IComponent component)
+ public static PythonDesignerRootComponent CreateDesignerRootComponent(IComponent component)
{
return new PythonDesignerRootComponent(component);
}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerRootComponent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerRootComponent.cs
index 7ebfa7fce6..2bd43da85f 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerRootComponent.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerRootComponent.cs
@@ -6,7 +6,9 @@
//
using System;
+using System.Collections.Generic;
using System.ComponentModel;
+using System.Windows.Forms;
namespace ICSharpCode.PythonBinding
{
@@ -54,6 +56,60 @@ namespace ICSharpCode.PythonBinding
PythonDesignerComponent[] components = base.GetChildComponents();
Array.Reverse(components);
return components;
- }
+ }
+
+ ///
+ /// Returns true if non-visual components (e.g. Timer) are associated with this root component.
+ ///
+ public bool HasNonVisualChildComponents()
+ {
+ foreach (IComponent containerComponent in Component.Site.Container.Components) {
+ if (IsNonVisualComponent(containerComponent)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public PythonDesignerComponent[] GetNonVisualChildComponents()
+ {
+ List components = new List();
+ foreach (IComponent containerComponent in Component.Site.Container.Components) {
+ PythonDesignerComponent designerComponent = PythonDesignerComponentFactory.CreateDesignerComponent(containerComponent);
+ if (designerComponent.IsNonVisual) {
+ components.Add(designerComponent);
+ }
+ }
+ return components.ToArray();
+ }
+
+ ///
+ /// Appends an expression that creates an instance of the Container to hold non-visual components
+ ///
+ public void AppendCreateComponentsContainer(PythonCodeBuilder codeBuilder)
+ {
+ codeBuilder.AppendIndentedLine("self._components = " + typeof(Container).FullName + "()");
+ }
+
+ ///
+ /// Appends code to create all the non-visual component.
+ ///
+ public void AppendCreateNonVisualComponents(PythonCodeBuilder codeBuilder)
+ {
+ foreach (PythonDesignerComponent component in GetNonVisualChildComponents()) {
+ component.AppendCreateInstance(codeBuilder, "self._components");
+ }
+ }
+
+ ///
+ /// Appends code to set all the non-visual component properties.
+ ///
+ ///
+ public void AppendNonVisualComponents(PythonCodeBuilder codeBuilder)
+ {
+ foreach (PythonDesignerComponent component in GetNonVisualChildComponents()) {
+ component.AppendComponent(codeBuilder);
+ }
+ }
}
}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonListViewComponent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonListViewComponent.cs
index ff0c0a595f..0809a6bf71 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonListViewComponent.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonListViewComponent.cs
@@ -28,7 +28,7 @@ namespace ICSharpCode.PythonBinding
// Append list view item creation first.
int count = 1;
foreach (ListViewItem item in GetListViewItems(Component)) {
- AppendObjectCreation(codeBuilder, item, count, GetConstructorParameters(item));
+ AppendCreateInstance(codeBuilder, item, count, GetConstructorParameters(item));
++count;
}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/DeserializeComponentAssignmentTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/DeserializeComponentAssignmentTestFixture.cs
index b2bbb3963e..9544054ec2 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/DeserializeComponentAssignmentTestFixture.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/DeserializeComponentAssignmentTestFixture.cs
@@ -27,10 +27,7 @@ namespace PythonBinding.Tests.Designer
public override string GetPythonCode()
{
- button = new Button();
- button.Name = "button1";
- base.componentCreator.Add(button, "button1");
-
+ button = (Button)base.componentCreator.CreateInstance(typeof(Button), new object[0], "button1", false);
return "self.AcceptButton = self._button1";
}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateListViewItemTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateListViewItemTestFixture.cs
index f77edb0187..5629f34399 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateListViewItemTestFixture.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateListViewItemTestFixture.cs
@@ -249,5 +249,11 @@ namespace PythonBinding.Tests.Designer
Assert.AreEqual(expectedCode, createListViewChildComponentsCode);
}
+
+ [Test]
+ public void ColumnHeaderIsHiddenFromDesigner()
+ {
+ Assert.IsTrue(PythonDesignerComponent.IsHiddenFromDesigner(columnHeader1));
+ }
}
}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs
index 7b00aaa6b3..dd8a433bf5 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs
@@ -26,6 +26,7 @@ namespace PythonBinding.Tests.Designer
Size openMenuItemSize;
Size exitMenuItemSize;
Size editMenuItemSize;
+ bool nonVisualComponents;
[TestFixtureSetUp]
public void SetUpFixture()
@@ -75,6 +76,9 @@ namespace PythonBinding.Tests.Designer
exitMenuItemSize = exitMenuItem.Size;
editMenuItemSize = editMenuItem.Size;
+ PythonDesignerRootComponent rootComponent = new PythonDesignerRootComponent(form);
+ nonVisualComponents = rootComponent.HasNonVisualChildComponents();
+
PythonControl pythonForm = new PythonControl(" ");
generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form);
}
@@ -142,10 +146,16 @@ namespace PythonBinding.Tests.Designer
Assert.AreEqual(expectedCode, generatedPythonCode, generatedPythonCode);
}
-
+
+ [Test]
+ public void NoNonVisualComponents()
+ {
+ Assert.IsFalse(nonVisualComponents);
+ }
+
string SizeToString(Size size)
{
return PythonPropertyValueAssignment.ToString(size);
- }
+ }
}
}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateTimerTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateTimerTestFixture.cs
new file mode 100644
index 0000000000..5203012f43
--- /dev/null
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateTimerTestFixture.cs
@@ -0,0 +1,79 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.Drawing;
+using System.Windows.Forms;
+using ICSharpCode.PythonBinding;
+using NUnit.Framework;
+using PythonBinding.Tests.Utils;
+
+namespace PythonBinding.Tests.Designer
+{
+ [TestFixture]
+ public class GenerateTimerTestFixture
+ {
+ string generatedPythonCode;
+ bool hasNonVisualChildComponents;
+
+ [TestFixtureSetUp]
+ public void SetUpFixture()
+ {
+ 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");
+
+ Timer timer = (Timer)host.CreateComponent(typeof(Timer), "timer1");
+ descriptors = TypeDescriptor.GetProperties(timer);
+ namePropertyDescriptor = descriptors.Find("Interval", false);
+ namePropertyDescriptor.SetValue(timer, 1000);
+
+ string indentString = " ";
+ PythonDesignerRootComponent designerRootComponent = new PythonDesignerRootComponent(form);
+ hasNonVisualChildComponents = designerRootComponent.HasNonVisualChildComponents();
+
+ PythonControl pythonControl = new PythonControl(indentString);
+ generatedPythonCode = pythonControl.GenerateInitializeComponentMethod(form);
+ }
+ }
+
+ [Test]
+ public void HasNonVisualChildComponents()
+ {
+ Assert.IsTrue(hasNonVisualChildComponents);
+ }
+
+ [Test]
+ public void GeneratedCode()
+ {
+ string expectedCode = "def InitializeComponent(self):\r\n" +
+ " self._components = System.ComponentModel.Container()\r\n" +
+ " self._timer1 = System.Windows.Forms.Timer(self._components)\r\n" +
+ " self.SuspendLayout()\r\n" +
+ " # \r\n" +
+ " # timer1\r\n" +
+ " # \r\n" +
+ " self._timer1.Interval = 1000\r\n" +
+ " # \r\n" +
+ " # MainForm\r\n" +
+ " # \r\n" +
+ " self.ClientSize = System.Drawing.Size(284, 264)\r\n" +
+ " self.Name = \"MainForm\"\r\n" +
+ " self.ResumeLayout(False)\r\n" +
+ " self.PerformLayout()\r\n";
+
+ Assert.AreEqual(expectedCode, generatedPythonCode, generatedPythonCode);
+ }
+ }
+}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadTextBoxTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadTextBoxTestFixture.cs
index 2f2a99a5eb..656040c8b1 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadTextBoxTestFixture.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadTextBoxTestFixture.cs
@@ -58,7 +58,7 @@ namespace PythonBinding.Tests.Designer
[Test]
public void TextBoxInstanceCreated()
{
- CreatedInstance instance = new CreatedInstance(typeof(TextBox), new List