Browse Source

Python forms designer now generates code for the items inside a custom collection on a control.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4641 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Matt Ward 16 years ago
parent
commit
2f9723d453
  1. 71
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs
  2. 4
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonListViewComponent.cs
  3. 4
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonTableLayoutPanelComponent.cs
  4. 4
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonTreeViewComponent.cs
  5. 89
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateCustomCollectionItemsTestFixture.cs
  6. 3
      src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj
  7. 27
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/CustomUserControl.cs
  8. 46
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/FooItemCollection.cs

71
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs

@ -24,6 +24,8 @@ namespace ICSharpCode.PythonBinding @@ -24,6 +24,8 @@ namespace ICSharpCode.PythonBinding
/// </summary>
public class PythonDesignerComponent
{
delegate void AppendCollectionContent(PythonCodeBuilder codeBuilder, object item, int count);
IComponent component;
static readonly Attribute[] notDesignOnlyFilter = new Attribute[] { DesignOnlyAttribute.No };
static readonly DesignerSerializationVisibility[] notHiddenDesignerVisibility = new DesignerSerializationVisibility[] { DesignerSerializationVisibility.Content, DesignerSerializationVisibility.Visible };
@ -208,19 +210,14 @@ namespace ICSharpCode.PythonBinding @@ -208,19 +210,14 @@ namespace ICSharpCode.PythonBinding
/// </summary>
public virtual void AppendCreateInstance(PythonCodeBuilder codeBuilder)
{
string parameters = String.Empty;
if (HasIContainerConstructor()) {
codeBuilder.InsertCreateComponentsContainer();
AppendCreateInstance(codeBuilder, "self._components");
} else {
AppendComponentCreation(codeBuilder, component);
}
}
public void AppendCreateInstance(PythonCodeBuilder codeBuilder, string parameters)
{
parameters = "self._components";
}
AppendComponentCreation(codeBuilder, component, parameters);
}
/// <summary>
/// Appends the code to create the child components.
/// </summary>
@ -420,12 +417,15 @@ namespace ICSharpCode.PythonBinding @@ -420,12 +417,15 @@ namespace ICSharpCode.PythonBinding
{
AppendComponentCreation(codeBuilder, component, String.Empty);
}
/// <summary>
/// Appends the code to create the specified IComponent
/// </summary>
public void AppendComponentCreation(PythonCodeBuilder codeBuilder, IComponent component, string parameters)
{
if (ShouldAppendCollectionContent) {
AppendForEachCollectionContent(codeBuilder, component, AppendCollectionContentCreation);
}
codeBuilder.AppendIndentedLine("self._" + component.Site.Name + " = " + component.GetType().FullName + "(" + parameters + ")");
}
@ -471,6 +471,24 @@ namespace ICSharpCode.PythonBinding @@ -471,6 +471,24 @@ namespace ICSharpCode.PythonBinding
}
}
/// <summary>
/// Looks for any collections that have objects that should be created as local variables
/// in the InitializeComponent method.
/// </summary>
public void AppendCollectionContentCreation(PythonCodeBuilder codeBuilder, object item, int count)
{
AppendCreateInstance(codeBuilder, item, count, new object[0]);
}
/// <summary>
/// Looks for any collections that have objects that will have been added as local variables
/// and appends their property values.
/// </summary>
public void AppendCollectionContentProperties(PythonCodeBuilder codeBuilder, object item, int count)
{
AppendProperties(codeBuilder, GetVariableName(item, count), item);
}
/// <summary>
/// Gets the variable name for the specified type.
/// </summary>
@ -501,7 +519,6 @@ namespace ICSharpCode.PythonBinding @@ -501,7 +519,6 @@ namespace ICSharpCode.PythonBinding
/// </remarks>
public static void AppendMethodCallWithArrayParameter(PythonCodeBuilder codeBuilder, string propertyOwnerName, object propertyOwner, PropertyDescriptor propertyDescriptor, bool reverse)
{
IComponent component = propertyOwner as IComponent;
ICollection collectionProperty = propertyDescriptor.GetValue(propertyOwner) as ICollection;
if (collectionProperty != null) {
MethodInfo addRangeMethod = GetAddRangeSerializationMethod(collectionProperty);
@ -529,7 +546,7 @@ namespace ICSharpCode.PythonBinding @@ -529,7 +546,7 @@ namespace ICSharpCode.PythonBinding
/// </summary>
public void AppendProperty(PythonCodeBuilder codeBuilder, string propertyOwnerName, object obj, PropertyDescriptor propertyDescriptor)
{
object propertyValue = propertyDescriptor.GetValue(obj);
object propertyValue = propertyDescriptor.GetValue(obj);
ExtenderProvidedPropertyAttribute extender = GetExtenderAttribute(propertyDescriptor);
if (extender != null) {
AppendExtenderProperty(codeBuilder, propertyOwnerName, extender, propertyDescriptor, propertyValue);
@ -601,6 +618,10 @@ namespace ICSharpCode.PythonBinding @@ -601,6 +618,10 @@ namespace ICSharpCode.PythonBinding
/// </summary>
public void AppendProperties(PythonCodeBuilder codeBuilder, string propertyOwnerName, object obj)
{
if (ShouldAppendCollectionContent) {
AppendForEachCollectionContent(codeBuilder, obj, AppendCollectionContentProperties);
}
foreach (PropertyDescriptor property in GetSerializableProperties(obj)) {
if (!IgnoreProperty(property)) {
AppendProperty(codeBuilder, propertyOwnerName, obj, property);
@ -781,6 +802,10 @@ namespace ICSharpCode.PythonBinding @@ -781,6 +802,10 @@ namespace ICSharpCode.PythonBinding
return false;
}
protected virtual bool ShouldAppendCollectionContent {
get { return true; }
}
static bool HasSitedComponents(PythonDesignerComponent[] components)
{
foreach (PythonDesignerComponent component in components) {
@ -899,5 +924,27 @@ namespace ICSharpCode.PythonBinding @@ -899,5 +924,27 @@ namespace ICSharpCode.PythonBinding
}
return false;
}
/// <summary>
/// Calls the AppendCollectionContent method for every item in all collections that need their content
/// serialized.
/// </summary>
void AppendForEachCollectionContent(PythonCodeBuilder codeBuilder, object component, AppendCollectionContent appendCollectionContent)
{
foreach (PropertyDescriptor propertyDescriptor in GetSerializableContentProperties(component)) {
ICollection collection = propertyDescriptor.GetValue(component) as ICollection;
if (collection != null) {
int count = 1;
foreach (object item in collection) {
if (item is IComponent) {
// Ignore.
} else {
appendCollectionContent(codeBuilder, item, count);
}
++count;
}
}
}
}
}
}

4
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonListViewComponent.cs

@ -58,6 +58,10 @@ namespace ICSharpCode.PythonBinding @@ -58,6 +58,10 @@ namespace ICSharpCode.PythonBinding
AppendListViewGroupProperties(codeBuilder);
AppendComponentProperties(codeBuilder, true, false);
}
protected override bool ShouldAppendCollectionContent {
get { return false; }
}
/// <summary>
/// Gets the parameters to the ListViewItem constructor.

4
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonTableLayoutPanelComponent.cs

@ -30,6 +30,10 @@ namespace ICSharpCode.PythonBinding @@ -30,6 +30,10 @@ namespace ICSharpCode.PythonBinding
base.AppendMethodCallWithArrayParameter(codeBuilder, propertyOwnerName, propertyOwner, propertyDescriptor);
}
}
protected override bool ShouldAppendCollectionContent {
get { return false; }
}
bool IsStylesProperty(string name)
{

4
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonTreeViewComponent.cs

@ -51,6 +51,10 @@ namespace ICSharpCode.PythonBinding @@ -51,6 +51,10 @@ namespace ICSharpCode.PythonBinding
AppendComponentProperties(codeBuilder, true, false);
}
protected override bool ShouldAppendCollectionContent {
get { return false; }
}
void AppendCreateInstance(PythonCodeBuilder codeBuilder, List<PythonDesignerTreeNode> nodes)
{
object[] parameters = new object[0];

89
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateCustomCollectionItemsTestFixture.cs

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Drawing;
using System.Windows.Forms;
using ICSharpCode.PythonBinding;
using NUnit.Framework;
using PythonBinding.Tests.Utils;
namespace PythonBinding.Tests.Designer
{
/// <summary>
/// Tests that a custom collection class generates the correct code.
/// The collection class should be a property of a custom component or user control
/// and it should be marked with DesignerSerializationVisibility.Content.
/// </summary>
[TestFixture]
public class GenerateCustomCollectionItemsTestFixture
{
string generatedPythonCode;
[TestFixtureSetUp]
public void SetUpFixture()
{
using (DesignSurface designSurface = new DesignSurface(typeof(Form))) {
IDesignerHost host = (IDesignerHost)designSurface.GetService(typeof(IDesignerHost));
IEventBindingService eventBindingService = new MockEventBindingService(host);
Form form = (Form)host.RootComponent;
form.ClientSize = new Size(200, 300);
PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(form);
PropertyDescriptor namePropertyDescriptor = descriptors.Find("Name", false);
namePropertyDescriptor.SetValue(form, "MainForm");
// Add custom control
CustomUserControl userControl = (CustomUserControl)host.CreateComponent(typeof(CustomUserControl), "userControl1");
userControl.Location = new Point(0, 0);
userControl.ClientSize = new Size(200, 100);
userControl.FooItems.Add(new FooItem("aa"));
userControl.FooItems.Add(new FooItem("bb"));
form.Controls.Add(userControl);
PythonControl pythonForm = new PythonControl(" ");
generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form);
}
}
[Test]
public void GeneratedCode()
{
string expectedCode = "def InitializeComponent(self):\r\n" +
" fooItem1 = PythonBinding.Tests.Utils.FooItem()\r\n" +
" fooItem2 = PythonBinding.Tests.Utils.FooItem()\r\n" +
" self._userControl1 = PythonBinding.Tests.Utils.CustomUserControl()\r\n" +
" self.SuspendLayout()\r\n" +
" # \r\n" +
" # userControl1\r\n" +
" # \r\n" +
" fooItem1.Text = \"aa\"\r\n" +
" fooItem2.Text = \"bb\"\r\n" +
" self._userControl1.FooItems.AddRange(System.Array[PythonBinding.Tests.Utils.FooItem](\r\n" +
" [fooItem1,\r\n" +
" fooItem2]))\r\n" +
" self._userControl1.Location = System.Drawing.Point(0, 0)\r\n" +
" self._userControl1.Name = \"userControl1\"\r\n" +
" self._userControl1.Size = System.Drawing.Size(200, 100)\r\n" +
" self._userControl1.TabIndex = 0\r\n" +
" # \r\n" +
" # MainForm\r\n" +
" # \r\n" +
" self.ClientSize = System.Drawing.Size(200, 300)\r\n" +
" self.Controls.Add(self._userControl1)\r\n" +
" self.Name = \"MainForm\"\r\n" +
" self.ResumeLayout(False)\r\n" +
" self.PerformLayout()\r\n";
Assert.AreEqual(expectedCode, generatedPythonCode, generatedPythonCode);
}
}
}

3
src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj

@ -189,6 +189,7 @@ @@ -189,6 +189,7 @@
<Compile Include="Designer\GenerateComboBoxItemsTestFixture.cs" />
<Compile Include="Designer\GenerateContextMenuStripTestFixture.cs" />
<Compile Include="Designer\GenerateCursorFormTestFixture.cs" />
<Compile Include="Designer\GenerateCustomCollectionItemsTestFixture.cs" />
<Compile Include="Designer\GenerateDataSetTestFixture.cs" />
<Compile Include="Designer\GeneratedControlOrderingTestFixture.cs" />
<Compile Include="Designer\GenerateDoubleBufferedFormTestFixture.cs" />
@ -327,6 +328,7 @@ @@ -327,6 +328,7 @@
<Compile Include="Utils\ConvertedFile.cs" />
<Compile Include="Utils\CreatedComponent.cs" />
<Compile Include="Utils\CreatedInstance.cs" />
<Compile Include="Utils\CustomUserControl.cs" />
<Compile Include="Utils\DerivedAddInOptions.cs" />
<Compile Include="Utils\DerivedApplicationSettingsPanel.cs" />
<Compile Include="Utils\DerivedCompilingOptionsPanel.cs" />
@ -337,6 +339,7 @@ @@ -337,6 +339,7 @@
<Compile Include="Utils\DerivedPythonDesignerLoader.cs" />
<Compile Include="Utils\DerivedPythonFormsDesignerDisplayBinding.cs" />
<Compile Include="Utils\DerivedToolStripMenuItem.cs" />
<Compile Include="Utils\FooItemCollection.cs" />
<Compile Include="Utils\MockClass.cs" />
<Compile Include="Utils\MockComponentCreator.cs" />
<Compile Include="Utils\MockDebugger.cs" />

27
src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/CustomUserControl.cs

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace PythonBinding.Tests.Utils
{
public class CustomUserControl : UserControl
{
FooItemCollection fooItems = new FooItemCollection();
public CustomUserControl()
{
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public FooItemCollection FooItems {
get { return fooItems; }
}
}
}

46
src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/FooItemCollection.cs

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace PythonBinding.Tests.Utils
{
public class FooItem
{
string text = String.Empty;
public FooItem()
{
}
public FooItem(string text)
{
this.text = text;
}
public string Text {
get { return text; }
set { text = value; }
}
}
public class FooItemCollection : Collection<FooItem>
{
public FooItemCollection()
{
}
public void AddRange(FooItem[] items)
{
foreach (FooItem item in items) {
Add(item);
}
}
}
}
Loading…
Cancel
Save