diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs
index 9d4477fd3c..8161f13804 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs
@@ -202,14 +202,38 @@ namespace ICSharpCode.PythonBinding
}
return null;
}
+
+ ///
+ /// Looks for a field in the component with the given name.
+ ///
+ public static object GetInheritedObject(string name, object component)
+ {
+ if (component != null) {
+ FieldInfo[] fields = component.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
+ foreach (FieldInfo field in fields) {
+ if (String.Equals(name, field.Name, StringComparison.InvariantCultureIgnoreCase)) {
+ return field.GetValue(component);
+ }
+ }
+ }
+ return null;
+ }
///
/// Gets the object that the field expression variable refers to.
///
+ ///
+ /// This method will also check form's base class for any inherited objects that match
+ /// the object being referenced.
+ ///
public object GetObject(IComponentCreator componentCreator)
{
if (variableName.Length > 0) {
- return componentCreator.GetComponent(variableName);
+ object component = componentCreator.GetComponent(variableName);
+ if (component != null) {
+ return component;
+ }
+ return GetInheritedObject(variableName, componentCreator.RootComponent);
}
return componentCreator.RootComponent;
}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs
index 1eff0315d9..9e85fe4bfc 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs
@@ -284,25 +284,46 @@ namespace ICSharpCode.PythonBinding
}
///
- /// Returns true if the component has an InheritanceAttribute set to InheritanceLevel.InheritedReadOnly
+ /// Returns true if the component has an InheritanceAttribute set to InheritanceLevel.Inherited or
+ /// InheritanceLevel.InheritedReadOnly
///
- public static bool IsInheritedReadOnlyComponent(object component)
+ public static bool IsInheritedComponent(object component)
{
if (component != null) {
- AttributeCollection attributes = TypeDescriptor.GetAttributes(component);
- InheritanceAttribute attribute = (InheritanceAttribute)attributes[typeof(InheritanceAttribute)];
- if (attribute != null) {
- return attribute.InheritanceLevel == InheritanceLevel.InheritedReadOnly;
- }
+ InheritanceAttribute attribute = GetInheritanceAttribute(component);
+ return attribute.InheritanceLevel != InheritanceLevel.NotInherited;
}
return false;
}
+ ///
+ /// Returns true if the component has an InheritanceAttribute set to InheritanceLevel.Inherited or
+ /// InheritanceLevel.InheritedReadOnly
+ ///
+ public bool IsInherited {
+ get { return IsInheritedComponent(component); }
+ }
+
///
/// Returns true if the component has an InheritanceAttribute set to InheritanceLevel.InheritedReadOnly
///
public bool IsInheritedReadOnly {
- get { return IsInheritedReadOnlyComponent(component); }
+ get {
+ InheritanceAttribute attribute = GetInheritanceAttribute(component);
+ if (attribute != null) {
+ return attribute.InheritanceLevel == InheritanceLevel.InheritedReadOnly;
+ }
+ return false;
+ }
+ }
+
+ public static InheritanceAttribute GetInheritanceAttribute(object component)
+ {
+ if (component != null) {
+ AttributeCollection attributes = TypeDescriptor.GetAttributes(component);
+ return attributes[typeof(InheritanceAttribute)] as InheritanceAttribute;
+ }
+ return null;
}
///
@@ -495,7 +516,7 @@ namespace ICSharpCode.PythonBinding
}
foreach (object item in collectionProperty) {
IComponent collectionComponent = item as IComponent;
- if (PythonDesignerComponent.IsSitedComponent(collectionComponent) && !PythonDesignerComponent.IsInheritedReadOnlyComponent(collectionComponent)) {
+ if (PythonDesignerComponent.IsSitedComponent(collectionComponent) && !PythonDesignerComponent.IsInheritedComponent(collectionComponent)) {
codeBuilder.AppendIndentedLine(propertyOwnerName + "." + propertyDescriptor.Name + "." + addMethod.Name + "(self._" + collectionComponent.Site.Name + ")");
}
}
@@ -639,9 +660,15 @@ namespace ICSharpCode.PythonBinding
///
/// Gets the owner of any properties generated (e.g. "self._textBox1").
+ /// For an inherited component the actual component name is used without any underscore prefix.
+ ///
public virtual string GetPropertyOwnerName()
{
- return "self._" + component.Site.Name;
+ string componentName = component.Site.Name;
+ if (IsInherited) {
+ return "self." + componentName;
+ }
+ return "self._" + componentName;
}
///
@@ -741,7 +768,7 @@ namespace ICSharpCode.PythonBinding
static bool HasSitedComponents(PythonDesignerComponent[] components)
{
foreach (PythonDesignerComponent component in components) {
- if (component.IsSited) {
+ if (component.IsSited && !component.IsInherited) {
return true;
}
}
@@ -751,7 +778,7 @@ namespace ICSharpCode.PythonBinding
void AppendCreateChildComponents(PythonCodeBuilder codeBuilder, PythonDesignerComponent[] childComponents)
{
foreach (PythonDesignerComponent designerComponent in childComponents) {
- if (designerComponent.IsSited) {
+ if (designerComponent.IsSited && !designerComponent.IsInherited) {
designerComponent.AppendCreateInstance(codeBuilder);
}
}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateInheritedProtectedPanelFormTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateInheritedProtectedPanelFormTestFixture.cs
new file mode 100644
index 0000000000..ff335c3189
--- /dev/null
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateInheritedProtectedPanelFormTestFixture.cs
@@ -0,0 +1,109 @@
+//
+//
+//
+//
+// $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
+{
+ class ProtectedPanelBaseForm : Form
+ {
+ protected Panel panel1 = new Panel();
+ Button button1 = new Button();
+
+ public ProtectedPanelBaseForm()
+ {
+ button1.Name = "button1";
+
+ panel1.Name = "panel1";
+ panel1.Location = new Point(5, 10);
+ panel1.Size = new Size(200, 100);
+ panel1.Controls.Add(button1);
+
+ Controls.Add(panel1);
+ }
+ }
+
+ class ProtectedPanelDerivedForm : ProtectedPanelBaseForm
+ {
+ [EditorBrowsableAttribute(EditorBrowsableState.Never)]
+ internal Point PanelLocation {
+ get { return panel1.Location; }
+ set { panel1.Location = value; }
+ }
+
+ [EditorBrowsableAttribute(EditorBrowsableState.Never)]
+ internal Size PanelSize {
+ get { return panel1.Size; }
+ set { panel1.Size = value; }
+ }
+
+ [EditorBrowsableAttribute(EditorBrowsableState.Never)]
+ internal Panel GetPanel()
+ {
+ return panel1;
+ }
+ }
+
+ ///
+ /// Tests that no code is generated for a protected panel control in the base class
+ /// that has child controls.
+ ///
+ [TestFixture]
+ public class GenerateInheritedProtectedPanelFormTestFixture
+ {
+ string generatedPythonCode;
+
+ [TestFixtureSetUp]
+ public void SetUpFixture()
+ {
+ using (DesignSurface designSurface = new DesignSurface(typeof(ProtectedPanelDerivedForm))) {
+ 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");
+
+ // Move protected panel so we generate code for the new location.
+ ProtectedPanelDerivedForm derivedForm = (ProtectedPanelDerivedForm)form;
+ derivedForm.PanelLocation = new Point(10, 15);
+
+ string indentString = " ";
+ PythonControl pythonForm = new PythonControl(indentString);
+ generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form);
+ }
+ }
+
+ [Test]
+ public void GeneratedCode()
+ {
+ string expectedCode = "def InitializeComponent(self):\r\n" +
+ " self.SuspendLayout()\r\n" +
+ " # \r\n" +
+ " # panel1\r\n" +
+ " # \r\n" +
+ " self.panel1.Location = System.Drawing.Point(10, 15)\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/LoadInheritedProtectedPanelFormTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadInheritedProtectedPanelFormTestFixture.cs
new file mode 100644
index 0000000000..1eebc84f30
--- /dev/null
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadInheritedProtectedPanelFormTestFixture.cs
@@ -0,0 +1,90 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+
+using ICSharpCode.PythonBinding;
+using IronPython.Compiler.Ast;
+using NUnit.Framework;
+using PythonBinding.Tests.Utils;
+
+namespace PythonBinding.Tests.Designer
+{
+ [TestFixture]
+ public class LoadInheritedProtectedPanelFormTestFixture : LoadFormTestFixtureBase
+ {
+ public override string PythonCode {
+ get {
+ base.ComponentCreator.AddType("PythonBinding.Tests.Designer.ProtectedPanelDerivedForm", typeof(ProtectedPanelDerivedForm));
+
+ return "class MainForm(PythonBinding.Tests.Designer.ProtectedPanelDerivedForm):\r\n" +
+ " def InitializeComponent(self):\r\n" +
+ " self.SuspendLayout()\r\n" +
+ " # \r\n" +
+ " # panel1\r\n" +
+ " # \r\n" +
+ " self.panel1.Location = System.Drawing.Point(10, 15)\r\n" +
+ " self.panel1.Size = System.Drawing.Size(108, 120)\r\n" +
+ " # \r\n" +
+ " # form1\r\n" +
+ " # \r\n" +
+ " self.Location = System.Drawing.Point(10, 20)\r\n" +
+ " self.Name = \"form1\"\r\n" +
+ " self.Controls.Add(self._textBox1)\r\n" +
+ " self.ResumeLayout(False)\r\n";
+ }
+ }
+
+ ProtectedPanelDerivedForm DerivedForm {
+ get { return Form as ProtectedPanelDerivedForm; }
+ }
+
+ [Test]
+ public void PanelLocation()
+ {
+ Assert.AreEqual(new Point(10, 15), DerivedForm.PanelLocation);
+ }
+
+ [Test]
+ public void PanelSize()
+ {
+ Assert.AreEqual(new Size(108, 120), DerivedForm.PanelSize);
+ }
+
+ [Test]
+ public void GetProtectedPanelObject()
+ {
+ Assert.AreEqual(DerivedForm.GetPanel(), PythonControlFieldExpression.GetInheritedObject("panel1", DerivedForm));
+ }
+
+ [Test]
+ public void GetProtectedPanelObjectIncorrectCase()
+ {
+ Assert.AreEqual(DerivedForm.GetPanel(), PythonControlFieldExpression.GetInheritedObject("PANEL1", DerivedForm));
+ }
+
+ [Test]
+ public void GetInheritedObjectPassedNull()
+ {
+ Assert.IsNull(PythonControlFieldExpression.GetInheritedObject("panel1", null));
+ }
+
+ [Test]
+ public void GetInheritedPanelObjectFromFieldExpression()
+ {
+ AssignmentStatement statement = PythonParserHelper.GetAssignmentStatement("self.panel1.Name = \"abc\"");
+ PythonControlFieldExpression field = PythonControlFieldExpression.Create(statement.Left[0] as MemberExpression);
+
+ Assert.AreEqual(DerivedForm.GetPanel(), field.GetObject(ComponentCreator));
+ }
+ }
+}
diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj
index 3ec24d2b90..c1cf54fd8d 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj
@@ -197,6 +197,7 @@
+
@@ -235,6 +236,7 @@
+