From b747259b4eb49e88f96240b6bd712468238d9ac2 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Tue, 18 Aug 2009 18:50:45 +0000 Subject: [PATCH] Python forms designer now calls all methods and explicit interface methods when loading InitializeComponent method. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4729 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/PythonComponentWalker.cs | 37 +++++++-- .../Src/PythonControlFieldExpression.cs | 10 ++- .../CallBeginInitOnLoadTestFixture.cs | 78 +++++++++++++++++++ .../Test/PythonBinding.Tests.csproj | 2 + .../Test/Utils/SupportInitCustomControl.cs | 48 ++++++++++++ 5 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/CallBeginInitOnLoadTestFixture.cs create mode 100644 src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/SupportInitCustomControl.cs diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonComponentWalker.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonComponentWalker.cs index 43441a703e..0e327d81f5 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonComponentWalker.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonComponentWalker.cs @@ -292,11 +292,6 @@ namespace ICSharpCode.PythonBinding /// void WalkMethodCall(CallExpression node) { - if (node.Args.Length == 0) { - // Ignore method calls with no parameters. - return; - } - // Try to get the object being called. Try the form first then // look for other controls. object member = PythonControlFieldExpression.GetMember(component, node); @@ -308,10 +303,40 @@ namespace ICSharpCode.PythonBinding // Execute the method on the object. if (member != null) { object[] args = deserializer.GetArguments(node).ToArray(); - member.GetType().InvokeMember(field.MethodName, BindingFlags.InvokeMethod, Type.DefaultBinder, member, args); + InvokeMethod(member, field.MethodName, args); + } + } + + void InvokeMethod(object obj, string name, object[] args) + { + Type type = obj.GetType(); + try { + type.InvokeMember(name, BindingFlags.InvokeMethod, Type.DefaultBinder, obj, args); + } catch (MissingMethodException ex) { + // Look for an explicitly implemented interface. + MethodInfo method = FindInterfaceMethod(type, name); + if (method != null) { + method.Invoke(obj, args); + } else { + throw ex; + } } } + /// + /// Looks for an explicitly implemented interface. + /// + MethodInfo FindInterfaceMethod(Type type, string name) + { + string nameMatch = "." + name; + foreach (MethodInfo method in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)) { + if (method.Name.EndsWith(nameMatch)) { + return method; + } + } + return null; + } + /// /// Creates a new instance with the specified name. /// diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs index 0fa5d82b04..5d50564bd5 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs @@ -329,6 +329,9 @@ namespace ICSharpCode.PythonBinding obj = componentCreator.GetInstance(variableName); if (obj == null) { obj = GetInheritedObject(memberName, componentCreator.RootComponent); + if ((obj == null) && !IsSelfReference) { + obj = componentCreator.GetInstance(fullMemberName); + } } } @@ -352,7 +355,10 @@ namespace ICSharpCode.PythonBinding public static object GetMember(object obj, CallExpression expression) { string[] memberNames = GetMemberNames(expression.Target as MemberExpression); - return GetMember(obj, memberNames, 1, memberNames.Length - 2); + if (ContainsSelfReference(memberNames)) { + return GetMember(obj, memberNames, 1, memberNames.Length - 2); + } + return null; } /// @@ -361,7 +367,7 @@ namespace ICSharpCode.PythonBinding /// The point at which to start looking in the memberNames. /// The last memberNames item to look at. static object GetMember(object obj, string[] memberNames, int startIndex, int endIndex) - { + { for (int i = startIndex; i <= endIndex; ++i) { Type type = obj.GetType(); string name = memberNames[i]; diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/CallBeginInitOnLoadTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/CallBeginInitOnLoadTestFixture.cs new file mode 100644 index 0000000000..4b650eb79e --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/CallBeginInitOnLoadTestFixture.cs @@ -0,0 +1,78 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Drawing; +using System.Windows.Forms; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Designer +{ + /// + /// Tests that the control's BeginInit and EndInit methods are called. + /// + [TestFixture] + public class CallBeginInitOnLoadTestFixture : LoadFormTestFixtureBase + { + public override string PythonCode { + get { + ComponentCreator.AddType("PythonBinding.Tests.Utils.SupportInitCustomControl", typeof(SupportInitCustomControl)); + + return "class TestForm(System.Windows.Forms.Form):\r\n" + + " def InitializeComponent(self):\r\n" + + " self._control = PythonBinding.Tests.Utils.SupportInitCustomControl()\r\n" + + " self._control.BeginInit()\r\n" + + " localVariable = PythonBinding.Tests.Utils.SupportInitCustomControl()\r\n" + + " localVariable.BeginInit()\r\n" + + " self.SuspendLayout()\r\n" + + " # \r\n" + + " # TestForm\r\n" + + " # \r\n" + + " self.AccessibleRole = System.Windows.Forms.AccessibleRole.None\r\n" + + " self.Controls.Add(self._control)\r\n" + + " self.Name = \"TestForm\"\r\n" + + " self._control.EndInit()\r\n" + + " localVariable.EndInit()\r\n" + + " self.ResumeLayout(False)\r\n"; + } + } + + public SupportInitCustomControl Control { + get { return Form.Controls[0] as SupportInitCustomControl; } + } + + public SupportInitCustomControl LocalControl { + get { return base.ComponentCreator.GetInstance("localVariable") as SupportInitCustomControl; } + } + + [Test] + public void BeginInitCalled() + { + Assert.IsTrue(Control.IsBeginInitCalled); + } + + [Test] + public void EndInitCalled() + { + Assert.IsTrue(Control.IsEndInitCalled); + } + + [Test] + public void BeginInitCalledOnLocalVariable() + { + Assert.IsTrue(LocalControl.IsBeginInitCalled); + } + + [Test] + public void EndInitCalledOnLocalVariable() + { + Assert.IsTrue(LocalControl.IsEndInitCalled); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj index 6f1ece3ef0..9c26ae483e 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj @@ -162,6 +162,7 @@ + @@ -374,6 +375,7 @@ + diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/SupportInitCustomControl.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/SupportInitCustomControl.cs new file mode 100644 index 0000000000..f3038f002c --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/SupportInitCustomControl.cs @@ -0,0 +1,48 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.ComponentModel; +using System.Windows.Forms; + +namespace PythonBinding.Tests.Utils +{ + public class SupportInitCustomControl : UserControl, ISupportInitialize + { + bool beginInitCalled; + bool endInitCalled; + + public SupportInitCustomControl() + { + } + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public bool IsBeginInitCalled { + get { return beginInitCalled; } + } + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public bool IsEndInitCalled { + get { return endInitCalled; } + } + + /// + /// Deliberately making the interface explicit for the BeginInit method but not the EndInit method. + /// + void ISupportInitialize.BeginInit() + { + beginInitCalled = true; + } + + public void EndInit() + { + endInitCalled = true; + } + } +}