Browse Source

Python forms designer now supports generating code for ListViewItem's text.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4044 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Matt Ward 16 years ago
parent
commit
510f9c1e5b
  1. 5
      src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj
  2. 81
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeBuilder.cs
  3. 559
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControl.cs
  4. 590
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponent.cs
  5. 36
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponentFactory.cs
  6. 49
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerRootComponent.cs
  7. 82
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonListViewComponent.cs
  8. 45
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/CreateDesignerComponentTests.cs
  9. 12
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/FindAddRangeMethodTests.cs
  10. 4
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateAcceptButtonFormTestFixture.cs
  11. 172
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateListViewItemTestFixture.cs
  12. 6
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs
  13. 24
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateSimpleFormTestFixture.cs
  14. 94
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateTextBoxFormTestFixture.cs
  15. 2
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GetSerializableContentPropertiesTestFixture.cs
  16. 2
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/IgnoreDesignTimePropertiesTestFixture.cs
  17. 17
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/IsSitedComponentTests.cs
  18. 76
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonCodeBuilderTests.cs
  19. 2
      src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj
  20. 8
      src/AddIns/BackendBindings/Python/PythonBinding/Test/TODO.txt

5
src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj

@ -80,6 +80,7 @@ @@ -80,6 +80,7 @@
<Compile Include="Src\PythonAstWalker.cs" />
<Compile Include="Src\PythonCodeCompletionBinding.cs" />
<Compile Include="Src\PythonCodeDeserializer.cs" />
<Compile Include="Src\PythonCodeBuilder.cs" />
<Compile Include="Src\PythonCompilerError.cs" />
<Compile Include="Src\PythonCompilerSink.cs" />
<Compile Include="Src\PythonConsole.cs" />
@ -87,15 +88,19 @@ @@ -87,15 +88,19 @@
<Compile Include="Src\PythonConsoleHost.cs" />
<Compile Include="Src\PythonConsolePad.cs" />
<Compile Include="Src\PythonControlFieldExpression.cs" />
<Compile Include="Src\PythonDesignerComponent.cs" />
<Compile Include="Src\PythonDesignerComponentFactory.cs" />
<Compile Include="Src\PythonDesignerGenerator.cs" />
<Compile Include="Src\PythonDesignerLoader.cs" />
<Compile Include="Src\PythonDesignerLoaderProvider.cs" />
<Compile Include="Src\PythonDesignerRootComponent.cs" />
<Compile Include="Src\PythonExpressionFinder.cs" />
<Compile Include="Src\PythonControl.cs" />
<Compile Include="Src\PythonFormsDesignerDisplayBinding.cs" />
<Compile Include="Src\PythonComponentWalker.cs" />
<Compile Include="Src\PythonComponentWalkerException.cs" />
<Compile Include="Src\PythonLanguageBinding.cs" />
<Compile Include="Src\PythonListViewComponent.cs" />
<Compile Include="Src\PythonOptionsPanel.cs" />
<Compile Include="Src\PythonOutputStream.cs" />
<Compile Include="Src\PythonOutputWindowPadDescriptor.cs" />

81
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeBuilder.cs

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
// <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.Text;
namespace ICSharpCode.PythonBinding
{
public class PythonCodeBuilder
{
StringBuilder codeBuilder = new StringBuilder();
string indentString = "\t";
int indent;
public PythonCodeBuilder()
{
}
/// <summary>
/// Gets or sets the string used for indenting.
/// </summary>
public string IndentString {
get { return indentString; }
set { indentString = value; }
}
/// <summary>
/// Returns the code.
/// </summary>
public override string ToString()
{
return codeBuilder.ToString();
}
/// <summary>
/// Appends text at the end of the current code.
/// </summary>
public void Append(string text)
{
codeBuilder.Append(text);
}
/// <summary>
/// Appends carriage return and line feed to the existing text.
/// </summary>
public void AppendLine()
{
Append("\r\n");
}
/// <summary>
/// Appends the text indented.
/// </summary>
public void AppendIndented(string text)
{
for (int i = 0; i < indent; ++i) {
codeBuilder.Append(indentString);
}
codeBuilder.Append(text);
}
public void AppendIndentedLine(string text)
{
AppendIndented(text + "\r\n");
}
public void IncreaseIndent()
{
indent++;
}
public void DecreaseIndent()
{
indent--;
}
}
}

559
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControl.cs

@ -25,65 +25,17 @@ namespace ICSharpCode.PythonBinding @@ -25,65 +25,17 @@ namespace ICSharpCode.PythonBinding
/// </summary>
public class PythonControl
{
StringBuilder codeBuilder;
PythonCodeBuilder codeBuilder;
string indentString = String.Empty;
int indent;
IEventBindingService eventBindingService;
static readonly Attribute[] notDesignOnlyFilter = new Attribute[] { DesignOnlyAttribute.No };
static readonly DesignerSerializationVisibility[] notHiddenDesignerVisibility = new DesignerSerializationVisibility[] { DesignerSerializationVisibility.Content, DesignerSerializationVisibility.Visible };
static readonly DesignerSerializationVisibility[] contentDesignerVisibility = new DesignerSerializationVisibility[] { DesignerSerializationVisibility.Content };
/// <summary>
/// Used so the EventBindingService.GetEventProperty method can be called to get the property descriptor
/// for an event.
/// </summary>
class PythonFormEventBindingService : EventBindingService
{
public PythonFormEventBindingService()
: base(new ServiceContainer())
{
}
protected override string CreateUniqueMethodName(IComponent component, EventDescriptor e)
{
return String.Empty;
}
protected override ICollection GetCompatibleMethods(EventDescriptor e)
{
return new ArrayList();
}
protected override bool ShowCode()
{
return false;
}
protected override bool ShowCode(int lineNumber)
{
return false;
}
protected override bool ShowCode(IComponent component, EventDescriptor e, string methodName)
{
return false;
}
}
public PythonControl()
: this("\t")
{
}
public PythonControl(string indentString)
: this(indentString, new PythonFormEventBindingService())
{
}
PythonControl(string indentString, IEventBindingService eventBindingService)
public PythonControl(string indentString)
{
this.indentString = indentString;
this.eventBindingService = eventBindingService;
}
/// <summary>
@ -91,10 +43,11 @@ namespace ICSharpCode.PythonBinding @@ -91,10 +43,11 @@ namespace ICSharpCode.PythonBinding
/// </summary>
public string GenerateInitializeComponentMethod(Control control)
{
codeBuilder = new StringBuilder();
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
AppendIndentedLine("def InitializeComponent(self):");
IncreaseIndent();
codeBuilder.AppendIndentedLine("def InitializeComponent(self):");
codeBuilder.IncreaseIndent();
GenerateInitializeComponentMethodBodyInternal(control);
@ -106,498 +59,26 @@ namespace ICSharpCode.PythonBinding @@ -106,498 +59,26 @@ namespace ICSharpCode.PythonBinding
/// </summary>
public string GenerateInitializeComponentMethodBody(Control control, int initialIndent)
{
codeBuilder = new StringBuilder();
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
indent = initialIndent;
for (int i = 0; i < initialIndent; ++i) {
codeBuilder.IncreaseIndent();
}
GenerateInitializeComponentMethodBodyInternal(control);
return codeBuilder.ToString();
}
/// <summary>
/// Gets a list of properties that should be serialized for the specified form.
/// </summary>
public static PropertyDescriptorCollection GetSerializableProperties(object obj)
{
return GetSerializableProperties(obj, notHiddenDesignerVisibility);
}
/// <summary>
/// Gets a list of properties that should have their content serialized for the specified form.
/// </summary>
public static PropertyDescriptorCollection GetSerializableContentProperties(object obj)
{
return GetSerializableProperties(obj, contentDesignerVisibility);
}
/// <summary>
/// Gets the serializable properties with the specified designer serialization visibility.
/// </summary>
public static PropertyDescriptorCollection GetSerializableProperties(object obj, DesignerSerializationVisibility[] visibility)
{
List<DesignerSerializationVisibility> requiredVisibility = new List<DesignerSerializationVisibility>(visibility);
List<PropertyDescriptor> properties = new List<PropertyDescriptor>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(obj, notDesignOnlyFilter).Sort()) {
if (requiredVisibility.Contains(property.SerializationVisibility)) {
if (property.ShouldSerializeValue(obj)) {
properties.Add(property);
}
}
}
return new PropertyDescriptorCollection(properties.ToArray());
}
/// <summary>
/// Determines whether the object is an IComponent and has a non-null ISite.
/// </summary>
public static bool IsSitedComponent(object obj)
{
IComponent component = obj as IComponent;
if (component != null) {
return component.Site != null;
}
return false;
}
/// <summary>
/// Gets the AddRange method on the object that is not hidden from the designer.
/// </summary>
public static MethodInfo GetAddRangeSerializationMethod(object obj)
{
foreach (MethodInfo methodInfo in obj.GetType().GetMethods()) {
if (methodInfo.Name == "AddRange") {
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length == 1) {
if (parameters[0].ParameterType.IsArray) {
if (!IsHiddenFromDesignerSerializer(methodInfo)) {
return methodInfo;
}
}
}
}
}
return null;
}
/// <summary>
/// Gets the Add serialization method that is not hidden from the designer.
/// </summary>
public static MethodInfo GetAddSerializationMethod(object obj)
{
foreach (MethodInfo methodInfo in obj.GetType().GetMethods()) {
if (methodInfo.Name == "Add") {
return methodInfo;
}
}
return null;
}
/// <summary>
/// Gets the type used in the array for the first parameter to the method.
/// </summary>
public static Type GetArrayParameterType(MethodInfo methodInfo)
{
if (methodInfo != null) {
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length > 0) {
Type arrayType = parameters[0].ParameterType;
return arrayType.GetElementType();
}
}
return null;
}
/// <summary>
/// Checks whether the method is marked with the DesignerSerializationVisibility.Hidden attribute.
/// </summary>
public static bool IsHiddenFromDesignerSerializer(MethodInfo methodInfo)
{
foreach (DesignerSerializationVisibilityAttribute attribute in methodInfo.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true)) {
if (attribute.Visibility == DesignerSerializationVisibility.Hidden) {
return true;
}
}
return false;
}
/// <summary>
/// Gets the child objects that need to be stored in the generated designer code on the specified object.
/// </summary>
/// <remarks>
/// For a MenuStrip the child components include the MenuStrip.Items.
/// For a Control the child components include the Control.Controls.
/// </remarks>
public static object[] GetChildComponents(object obj)
{
List<object> childComponents = new List<object>();
foreach (PropertyDescriptor property in GetSerializableContentProperties(obj)) {
ICollection collection = property.GetValue(obj) as ICollection;
if (collection != null) {
foreach (object childObject in collection) {
// Add only those IComponents which are sited and any other objects
// which are not IComponents.
IComponent component = childObject as IComponent;
if ((component == null) || IsSitedComponent(component)) {
childComponents.Add(childObject);
}
}
}
}
return childComponents.ToArray();
}
}
void GenerateInitializeComponentMethodBodyInternal(Control control)
{
AppendChildControlCreation(control);
AppendChildControlSuspendLayout(control.Controls);
AppendIndentedLine("self.SuspendLayout()");
AppendRootControl(control);
AppendChildControlResumeLayout(control.Controls);
AppendIndentedLine("self.ResumeLayout(False)");
AppendIndentedLine("self.PerformLayout()");
}
/// <summary>
/// Generates python code for the control's InitializeComponent method.
/// </summary>
void AppendRootControl(Control rootControl)
{
// Add the controls on the form.
foreach (Control control in rootControl.Controls) {
AppendComponent(control);
}
// Add root control.
AppendComponent(rootControl, false, false);
}
void AppendComponent(IComponent component)
{
AppendComponent(component, true, true);
}
/// <summary>
/// Generates python code for the component.
/// </summary>
void AppendComponent(IComponent component, bool addComponentNameToProperty, bool addChildComponentProperties)
{
AppendComment(component.Site.Name);
string propertyOwnerName = GetPropertyOwnerName(component, addComponentNameToProperty);
AppendProperties(propertyOwnerName, component);
AppendEventHandlers(propertyOwnerName, component);
if (addChildComponentProperties) {
AppendChildComponentProperties(component);
}
}
/// <summary>
/// Generates python code for an object's properties which is not an IComponent.
/// </summary>
void AppendObject(object obj, int count)
{
AppendProperties(GetVariableName(obj, count), obj);
}
/// <summary>
/// Appends a property to the InitializeComponents method.
/// </summary>
void AppendProperty(string propertyOwnerName, object obj, PropertyDescriptor propertyDescriptor)
{
object propertyValue = propertyDescriptor.GetValue(obj);
if (propertyValue == null) {
return;
}
if (propertyDescriptor.SerializationVisibility == DesignerSerializationVisibility.Visible) {
string propertyName = propertyOwnerName + "." + propertyDescriptor.Name;
Control control = propertyValue as Control;
if (control != null) {
AppendIndentedLine(propertyName + " = self._" + control.Name);
} else {
AppendIndentedLine(propertyName + " = " + PythonPropertyValueAssignment.ToString(propertyValue));
}
} else {
// DesignerSerializationVisibility.Content
AppendMethodCallWithArrayParameter(propertyOwnerName, obj, propertyDescriptor);
}
}
/// <summary>
/// Appends the comment lines before the control has its properties set.
/// </summary>
void AppendComment(string controlName)
{
AppendIndentedLine("# ");
AppendIndentedLine("# " + controlName);
AppendIndentedLine("# ");
}
/// <summary>
/// Increases the indent of any append lines.
/// </summary>
void IncreaseIndent()
{
++indent;
}
void DecreaseIndent()
{
--indent;
}
void Append(string text)
{
codeBuilder.Append(text);
}
void AppendLine()
{
Append("\r\n");
}
void AppendIndentedLine(string text)
{
AppendIndented(text + "\r\n");
}
void AppendIndented(string text)
{
for (int i = 0; i < indent; ++i) {
codeBuilder.Append(indentString);
}
codeBuilder.Append(text);
}
void AppendChildControlCreation(Control parentControl)
{
AppendChildComponentCreation(GetChildComponents(parentControl));
}
void AppendChildComponentCreation(ICollection components)
{
int count = 1;
foreach (object obj in components) {
IComponent component = obj as IComponent;
if (IsSitedComponent(component)) {
AppendComponentCreation(component);
AppendChildComponentCreation(GetChildComponents(component));
} else if (component == null) {
AppendChildObjectCreation(obj, count);
count++;
}
}
}
void AppendComponentCreation(IComponent component)
{
AppendComponentCreation(component.Site.Name, component);
}
void AppendComponentCreation(string name, object obj)
{
AppendIndentedLine("self._" + name + " = " + obj.GetType().FullName + "()");
}
void AppendChildObjectCreation(object obj, int count)
{
if (obj is String) {
// Do nothing.
} else {
AppendIndentedLine(GetVariableName(obj, count) + " = " + obj.GetType().FullName + "()");
}
}
void AppendChildControlSuspendLayout(Control.ControlCollection controls)
{
AppendChildControlLayoutMethodCalls(controls, new string[] {"SuspendLayout()"});
}
void AppendChildControlResumeLayout(Control.ControlCollection controls)
{
AppendChildControlLayoutMethodCalls(controls, new string[] {"ResumeLayout(False)", "PerformLayout()"});
}
void AppendChildControlLayoutMethodCalls(Control.ControlCollection controls, string[] methods)
{
foreach (Control control in controls) {
if (HasSitedChildComponents(control)) {
foreach (string method in methods) {
AppendIndentedLine("self._" + control.Name + "." + method);
}
AppendChildControlLayoutMethodCalls(control.Controls, methods);
}
}
}
/// <summary>
/// Generates code that wires an event to an event handler.
/// </summary>
/// <remarks>
/// Note that the EventDescriptorCollection.Sort method does not work if the
/// 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.</remarks>
void AppendEventHandlers(string propertyOwnerName, object component)
{
EventDescriptorCollection events = TypeDescriptor.GetEvents(component, notDesignOnlyFilter).Sort();
if (events.Count > 0) {
EventDescriptor dummyEventDescriptor = events[0];
}
foreach (EventDescriptor eventDescriptor in events) {
AppendEventHandler(propertyOwnerName, component, eventDescriptor);
}
}
void AppendEventHandler(string propertyOwnerName, object component, EventDescriptor eventDescriptor)
{
PropertyDescriptor propertyDescriptor = eventBindingService.GetEventProperty(eventDescriptor);
if (propertyDescriptor.ShouldSerializeValue(component)) {
string methodName = (string)propertyDescriptor.GetValue(component);
AppendIndentedLine(propertyOwnerName + "." + eventDescriptor.Name + " += self." + methodName);
}
}
bool HasSitedChildComponents(Control control)
{
return HasSitedComponents(GetChildComponents(control));
}
bool HasSitedComponents(ICollection items)
{
foreach (object item in items) {
if (IsSitedComponent(item)) {
return true;
}
}
return false;
}
void AppendSystemArray(string componentName, string methodName, string typeName, ICollection components)
{
if (components.Count > 0) {
AppendIndentedLine("self._" + componentName + "." + methodName + "(System.Array[" + typeName + "](");
IncreaseIndent();
int i = 0;
foreach (object component in components) {
if (i == 0) {
AppendIndented("[");
} else {
Append(",");
AppendLine();
AppendIndented(String.Empty);
}
if (component is IComponent) {
Append("self._" + ((IComponent)component).Site.Name);
} else if (component is String) {
Append(PythonPropertyValueAssignment.ToString(component));
} else {
Append(GetVariableName(component, i + 1));
}
++i;
}
Append("]))");
AppendLine();
DecreaseIndent();
}
}
void AppendProperties(string propertyOwnerName, object obj)
{
foreach (PropertyDescriptor property in GetSerializableProperties(obj)) {
AppendProperty(propertyOwnerName, obj, property);
}
}
string GetPropertyOwnerName(IComponent component, bool addComponentNameToProperty)
{
if (addComponentNameToProperty) {
return "self._" + component.Site.Name;
}
return "self";
}
/// <summary>
/// Appends the properties of any component that is contained in a collection property that is
/// marked as DesignerSerializationVisibility.Content.
/// </summary>
void AppendChildComponentProperties(object component)
{
foreach (PropertyDescriptor property in PythonControl.GetSerializableContentProperties(component)) {
object propertyCollection = property.GetValue(component);
ICollection collection = propertyCollection as ICollection;
if (collection != null) {
int count = 1;
foreach (object childObject in collection) {
IComponent childComponent = childObject as IComponent;
if (IsSitedComponent(childComponent)) {
AppendComponent(childComponent, true, true);
} else if (childComponent == null) {
AppendObject(childObject, count);
++count;
}
}
}
}
}
/// <summary>
/// Returns the sited components in the collection. If an object in the collection is not
/// an IComponent then this is added to the collection.
/// </summary>
ICollection GetSitedComponentsAndNonComponents(ICollection components)
{
List<object> sitedComponents = new List<object>();
foreach (object obj in components) {
IComponent component = obj as IComponent;
if (component == null || IsSitedComponent(component)) {
sitedComponents.Add(obj);
}
}
return sitedComponents.ToArray();
}
/// <summary>
/// Appends an array as a parameter and its associated method call.
/// </summary>
/// <remarks>
/// Looks for the AddRange method first. If that does not exist or is hidden from the designer the
/// Add method is looked for.
/// </remarks>
void AppendMethodCallWithArrayParameter(string propertyOwnerName, object propertyOwner, PropertyDescriptor propertyDescriptor)
{
IComponent component = propertyOwner as IComponent;
ICollection collectionProperty = propertyDescriptor.GetValue(propertyOwner) as ICollection;
if (collectionProperty != null) {
MethodInfo addRangeMethod = GetAddRangeSerializationMethod(collectionProperty);
if (addRangeMethod != null) {
Type arrayElementType = GetArrayParameterType(addRangeMethod);
AppendSystemArray(component.Site.Name, propertyDescriptor.Name + "." + addRangeMethod.Name, arrayElementType.FullName, GetSitedComponentsAndNonComponents(collectionProperty));
} else {
MethodInfo addMethod = GetAddSerializationMethod(collectionProperty);
ParameterInfo[] parameters = addMethod.GetParameters();
foreach (object item in collectionProperty) {
IComponent collectionComponent = item as IComponent;
if (IsSitedComponent(collectionComponent)) {
AppendIndentedLine(propertyOwnerName + "." + propertyDescriptor.Name + "." + addMethod.Name + "(self._" + collectionComponent.Site.Name + ")");
}
}
}
}
}
/// <summary>
/// Gets the variable name for the specified type.
/// </summary>
/// <remarks>
/// The variable name is simply the type name with the first character in lower case followed by the
/// count.
/// </remarks>
static string GetVariableName(object obj, int count)
{
string typeName = obj.GetType().Name;
return typeName[0].ToString().ToLowerInvariant() + typeName.Substring(1) + count;
PythonDesignerComponent rootDesignerComponent = PythonDesignerComponentFactory.CreateDesignerRootComponent(control);
rootDesignerComponent.AppendCreateChildComponents(codeBuilder);
rootDesignerComponent.AppendChildComponentsSuspendLayout(codeBuilder);
rootDesignerComponent.AppendSuspendLayout(codeBuilder);
rootDesignerComponent.AppendComponent(codeBuilder);
rootDesignerComponent.AppendChildComponentsResumeLayout(codeBuilder);
rootDesignerComponent.AppendResumeLayout(codeBuilder);
}
}
}

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

@ -0,0 +1,590 @@ @@ -0,0 +1,590 @@
// <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;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
namespace ICSharpCode.PythonBinding
{
/// <summary>
/// Represents an IComponent in the designer.
/// </summary>
public class PythonDesignerComponent
{
IComponent component;
static readonly Attribute[] notDesignOnlyFilter = new Attribute[] { DesignOnlyAttribute.No };
static readonly DesignerSerializationVisibility[] notHiddenDesignerVisibility = new DesignerSerializationVisibility[] { DesignerSerializationVisibility.Content, DesignerSerializationVisibility.Visible };
static readonly DesignerSerializationVisibility[] contentDesignerVisibility = new DesignerSerializationVisibility[] { DesignerSerializationVisibility.Content };
IEventBindingService eventBindingService;
protected static readonly string[] suspendLayoutMethods = new string[] {"SuspendLayout()"};
protected static readonly string[] resumeLayoutMethods = new string[] {"ResumeLayout(False)", "PerformLayout()"};
/// <summary>
/// Used so the EventBindingService.GetEventProperty method can be called to get the property descriptor
/// for an event.
/// </summary>
class PythonEventBindingService : EventBindingService
{
public PythonEventBindingService()
: base(new ServiceContainer())
{
}
protected override string CreateUniqueMethodName(IComponent component, EventDescriptor e)
{
return String.Empty;
}
protected override ICollection GetCompatibleMethods(EventDescriptor e)
{
return new ArrayList();
}
protected override bool ShowCode()
{
return false;
}
protected override bool ShowCode(int lineNumber)
{
return false;
}
protected override bool ShowCode(IComponent component, EventDescriptor e, string methodName)
{
return false;
}
}
public PythonDesignerComponent(IComponent component)
: this(component, new PythonEventBindingService())
{
}
PythonDesignerComponent(IComponent component, IEventBindingService eventBindingService)
{
this.component = component;
this.eventBindingService = eventBindingService;
}
/// <summary>
/// Gets a list of properties that should be serialized for the specified form.
/// </summary>
public static PropertyDescriptorCollection GetSerializableProperties(object obj)
{
return GetSerializableProperties(obj, notHiddenDesignerVisibility);
}
/// <summary>
/// Gets a list of properties that should have their content serialized for the specified form.
/// </summary>
public static PropertyDescriptorCollection GetSerializableContentProperties(object obj)
{
return GetSerializableProperties(obj, contentDesignerVisibility);
}
/// <summary>
/// Gets the serializable properties with the specified designer serialization visibility.
/// </summary>
public static PropertyDescriptorCollection GetSerializableProperties(object obj, DesignerSerializationVisibility[] visibility)
{
List<DesignerSerializationVisibility> requiredVisibility = new List<DesignerSerializationVisibility>(visibility);
List<PropertyDescriptor> properties = new List<PropertyDescriptor>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(obj, notDesignOnlyFilter).Sort()) {
if (requiredVisibility.Contains(property.SerializationVisibility)) {
if (property.ShouldSerializeValue(obj)) {
properties.Add(property);
}
}
}
return new PropertyDescriptorCollection(properties.ToArray());
}
/// <summary>
/// Checks whether the method is marked with the DesignerSerializationVisibility.Hidden attribute.
/// </summary>
public static bool IsHiddenFromDesignerSerializer(MethodInfo methodInfo)
{
foreach (DesignerSerializationVisibilityAttribute attribute in methodInfo.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true)) {
if (attribute.Visibility == DesignerSerializationVisibility.Hidden) {
return true;
}
}
return false;
}
/// <summary>
/// Gets the AddRange method on the object that is not hidden from the designer.
/// </summary>
public static MethodInfo GetAddRangeSerializationMethod(object obj)
{
foreach (MethodInfo methodInfo in obj.GetType().GetMethods()) {
if (methodInfo.Name == "AddRange") {
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length == 1) {
if (parameters[0].ParameterType.IsArray) {
if (!IsHiddenFromDesignerSerializer(methodInfo)) {
return methodInfo;
}
}
}
}
}
return null;
}
/// <summary>
/// Gets the Add serialization method that is not hidden from the designer.
/// </summary>
public static MethodInfo GetAddSerializationMethod(object obj)
{
foreach (MethodInfo methodInfo in obj.GetType().GetMethods()) {
if (methodInfo.Name == "Add") {
return methodInfo;
}
}
return null;
}
/// <summary>
/// Gets the type used in the array for the first parameter to the method.
/// </summary>
public static Type GetArrayParameterType(MethodInfo methodInfo)
{
if (methodInfo != null) {
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length > 0) {
Type arrayType = parameters[0].ParameterType;
return arrayType.GetElementType();
}
}
return null;
}
/// <summary>
/// Appends code that creates an instance of the component.
/// </summary>
public virtual void AppendCreateInstance(PythonCodeBuilder codeBuilder)
{
AppendComponentCreation(codeBuilder, component);
}
/// <summary>
/// Appends the code to create the child components.
/// </summary>
public void AppendCreateChildComponents(PythonCodeBuilder codeBuilder)
{
AppendCreateChildComponents(codeBuilder, GetChildComponents());
}
/// <summary>
/// Appends the component's properties.
/// </summary>
public virtual void AppendComponent(PythonCodeBuilder codeBuilder)
{
AppendComment(codeBuilder);
AppendComponentProperties(codeBuilder);
AppendChildComponentProperties(codeBuilder);
}
/// <summary>
/// Determines whether the object is an IComponent and has a non-null ISite.
/// </summary>
public static bool IsSitedComponent(object obj)
{
IComponent component = obj as IComponent;
if (component != null) {
return component.Site != null;
}
return false;
}
/// <summary>
/// Determines whether this designer component is sited.
/// </summary>
public bool IsSited {
get { return IsSitedComponent(component); }
}
/// <summary>
/// Gets the child objects that need to be stored in the generated designer code on the specified object.
/// </summary>
/// <remarks>
/// For a MenuStrip the child components include the MenuStrip.Items.
/// For a Control the child components include the Control.Controls.
/// </remarks>
public object[] GetChildComponents()
{
List<object> childComponents = new List<object>();
foreach (PropertyDescriptor property in GetSerializableContentProperties(component)) {
ICollection collection = property.GetValue(component) as ICollection;
if (collection != null) {
foreach (object childObject in collection) {
IComponent childComponent = childObject as IComponent;
if (IsSitedComponent(childComponent)) {
childComponents.Add(childObject);
}
}
}
}
return childComponents.ToArray();
}
/// <summary>
/// Appends SuspendLayout method call if the component has any sited child components.
/// </summary>
public virtual void AppendSuspendLayout(PythonCodeBuilder codeBuilder)
{
if (HasSitedChildComponents()) {
AppendMethodCalls(codeBuilder, suspendLayoutMethods);
}
}
/// <summary>
/// Appends the ResumeLayout and PerformLayout method calls if the component has any sited
/// child components.
/// </summary>
public virtual void AppendResumeLayout(PythonCodeBuilder codeBuilder)
{
if (HasSitedChildComponents()) {
AppendMethodCalls(codeBuilder, resumeLayoutMethods);
}
}
public void AppendChildComponentsSuspendLayout(PythonCodeBuilder codeBuilder)
{
AppendChildComponentsMethodCalls(codeBuilder, suspendLayoutMethods);
}
public void AppendChildComponentsResumeLayout(PythonCodeBuilder codeBuilder)
{
AppendChildComponentsMethodCalls(codeBuilder, resumeLayoutMethods);
}
void AppendChildComponentsMethodCalls(PythonCodeBuilder codeBuilder, string[] methods)
{
foreach (IComponent component in GetChildComponents()) {
PythonDesignerComponent designerComponent = PythonDesignerComponentFactory.CreateDesignerComponent(component);
if (designerComponent.component is Control) {
if (designerComponent.HasSitedChildComponents()) {
designerComponent.AppendMethodCalls(codeBuilder, methods);
}
}
designerComponent.AppendChildComponentsMethodCalls(codeBuilder, methods);
}
}
/// <summary>
/// Appends the code to create the specified object.
/// </summary>
public void AppendObjectCreation(PythonCodeBuilder codeBuilder, object obj, int count, object[] parameters)
{
if (obj is String) {
// Do nothing.
} else {
codeBuilder.AppendIndented(GetVariableName(obj, count) + " = " + obj.GetType().FullName);
codeBuilder.Append("(");
for (int i = 0; i < parameters.Length; ++i) {
if (i > 0) {
codeBuilder.Append(", ");
}
codeBuilder.Append(PythonPropertyValueAssignment.ToString(parameters[i]));
}
codeBuilder.Append(")");
codeBuilder.AppendLine();
}
}
/// <summary>
/// Appends the code to create the specified IComponent
/// </summary>
public void AppendComponentCreation(PythonCodeBuilder codeBuilder, IComponent component)
{
codeBuilder.AppendIndentedLine("self._" + component.Site.Name + " = " + component.GetType().FullName + "()");
}
/// <summary>
/// Generates the code for the component's properties.
/// </summary>
public void AppendComponentProperties(PythonCodeBuilder codeBuilder)
{
AppendComponentProperties(codeBuilder, true, false, false);
}
/// <summary>
/// Appends the properties of any component that is contained in a collection property that is
/// marked as DesignerSerializationVisibility.Content.
/// </summary>
public void AppendChildComponentProperties(PythonCodeBuilder codeBuilder)
{
foreach (PropertyDescriptor property in PythonDesignerComponent.GetSerializableContentProperties(component)) {
object propertyCollection = property.GetValue(component);
ICollection collection = propertyCollection as ICollection;
if (collection != null) {
foreach (object childObject in collection) {
IComponent childComponent = childObject as IComponent;
if (childComponent != null) {
PythonDesignerComponent designerComponent = PythonDesignerComponentFactory.CreateDesignerComponent(childComponent);
if (designerComponent.IsSited) {
designerComponent.AppendComponentProperties(codeBuilder, true, true, true);
}
}
}
}
}
}
/// <summary>
/// Generates python code for an object's properties when the object is not an IComponent.
/// </summary>
public void AppendObjectProperties(PythonCodeBuilder codeBuilder, object obj, int count)
{
AppendProperties(codeBuilder, PythonDesignerComponent.GetVariableName(obj, count), obj);
}
/// <summary>
/// Appends the comment lines containing the component name before the component has its properties set.
/// </summary>
///
public void AppendComment(PythonCodeBuilder codeBuilder)
{
codeBuilder.AppendIndentedLine("# ");
codeBuilder.AppendIndentedLine("# " + component.Site.Name);
codeBuilder.AppendIndentedLine("# ");
}
public bool HasSitedChildComponents()
{
return HasSitedComponents(GetChildComponents());
}
/// <summary>
/// Appends the method calls if this component.
/// </summary>
public void AppendMethodCalls(PythonCodeBuilder codeBuilder, string[] methods)
{
foreach (string method in methods) {
codeBuilder.AppendIndentedLine(GetPropertyOwnerName() + "." + method);
}
}
/// <summary>
/// Gets the variable name for the specified type.
/// </summary>
/// <remarks>
/// The variable name is simply the type name with the first character in lower case followed by the
/// count.
/// </remarks>
public static string GetVariableName(object obj, int count)
{
string typeName = obj.GetType().Name;
return typeName[0].ToString().ToLowerInvariant() + typeName.Substring(1) + count;
}
/// <summary>
/// Appends an array as a parameter and its associated method call.
/// </summary>
/// <remarks>
/// Looks for the AddRange method first. If that does not exist or is hidden from the designer the
/// Add method is looked for.
/// </remarks>
public static void AppendMethodCallWithArrayParameter(PythonCodeBuilder codeBuilder, string propertyOwnerName, object propertyOwner, PropertyDescriptor propertyDescriptor)
{
IComponent component = propertyOwner as IComponent;
ICollection collectionProperty = propertyDescriptor.GetValue(propertyOwner) as ICollection;
if (collectionProperty != null) {
MethodInfo addRangeMethod = GetAddRangeSerializationMethod(collectionProperty);
if (addRangeMethod != null) {
Type arrayElementType = GetArrayParameterType(addRangeMethod);
AppendSystemArray(codeBuilder, component.Site.Name, propertyDescriptor.Name + "." + addRangeMethod.Name, arrayElementType.FullName, GetSitedComponentsAndNonComponents(collectionProperty));
} else {
MethodInfo addMethod = GetAddSerializationMethod(collectionProperty);
ParameterInfo[] parameters = addMethod.GetParameters();
foreach (object item in collectionProperty) {
IComponent collectionComponent = item as IComponent;
if (PythonDesignerComponent.IsSitedComponent(collectionComponent)) {
codeBuilder.AppendIndentedLine(propertyOwnerName + "." + propertyDescriptor.Name + "." + addMethod.Name + "(self._" + collectionComponent.Site.Name + ")");
}
}
}
}
}
/// <summary>
/// Appends a property.
/// </summary>
public static void AppendProperty(PythonCodeBuilder codeBuilder, string propertyOwnerName, object obj, PropertyDescriptor propertyDescriptor)
{
object propertyValue = propertyDescriptor.GetValue(obj);
if (propertyValue == null) {
return;
}
if (propertyDescriptor.SerializationVisibility == DesignerSerializationVisibility.Visible) {
string propertyName = propertyOwnerName + "." + propertyDescriptor.Name;
Control control = propertyValue as Control;
if (control != null) {
codeBuilder.AppendIndentedLine(propertyName + " = self._" + control.Name);
} else {
codeBuilder.AppendIndentedLine(propertyName + " = " + PythonPropertyValueAssignment.ToString(propertyValue));
}
} else {
// DesignerSerializationVisibility.Content
AppendMethodCallWithArrayParameter(codeBuilder, propertyOwnerName, obj, propertyDescriptor);
}
}
/// <summary>
/// Appends the properties of the object to the code builder.
/// </summary>
public static void AppendProperties(PythonCodeBuilder codeBuilder, string propertyOwnerName, object obj)
{
foreach (PropertyDescriptor property in GetSerializableProperties(obj)) {
AppendProperty(codeBuilder, propertyOwnerName, obj, property);
}
}
/// <summary>
/// Appends the properties of the component.
/// </summary>
public void AppendProperties(PythonCodeBuilder codeBuilder)
{
AppendProperties(codeBuilder, GetPropertyOwnerName(), component);
}
/// <summary>
/// Generates python code for the component.
/// </summary>
public void AppendComponentProperties(PythonCodeBuilder codeBuilder, bool addComponentNameToProperty, bool addChildComponentProperties, bool addComment)
{
if (addComment) {
AppendComment(codeBuilder);
}
AppendProperties(codeBuilder);
AppendEventHandlers(codeBuilder, eventBindingService);
if (addChildComponentProperties) {
AppendChildComponentProperties(codeBuilder);
}
}
/// <summary>
/// Generates code that wires an event to an event handler.
/// </summary>
/// <remarks>
/// Note that the EventDescriptorCollection.Sort method does not work if the
/// 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.</remarks>
public void AppendEventHandlers(PythonCodeBuilder codeBuilder, IEventBindingService eventBindingService)
{
EventDescriptorCollection events = TypeDescriptor.GetEvents(component, notDesignOnlyFilter).Sort();
if (events.Count > 0) {
EventDescriptor dummyEventDescriptor = events[0];
}
foreach (EventDescriptor eventDescriptor in events) {
AppendEventHandler(codeBuilder, component, eventDescriptor, eventBindingService);
}
}
void AppendEventHandler(PythonCodeBuilder codeBuilder, object component, EventDescriptor eventDescriptor, IEventBindingService eventBindingService)
{
PropertyDescriptor propertyDescriptor = eventBindingService.GetEventProperty(eventDescriptor);
if (propertyDescriptor.ShouldSerializeValue(component)) {
string methodName = (string)propertyDescriptor.GetValue(component);
codeBuilder.AppendIndentedLine(GetPropertyOwnerName() + "." + eventDescriptor.Name + " += self." + methodName);
}
}
/// <summary>
/// Gets the owner of any properties generated (e.g. "self._textBox1").
public virtual string GetPropertyOwnerName()
{
return "self._" + component.Site.Name;
}
protected IComponent Component {
get { return component; }
}
static bool HasSitedComponents(ICollection items)
{
foreach (object item in items) {
if (IsSitedComponent(item)) {
return true;
}
}
return false;
}
void AppendCreateChildComponents(PythonCodeBuilder codeBuilder, ICollection childComponents)
{
foreach (object obj in childComponents) {
IComponent component = obj as IComponent;
PythonDesignerComponent designerComponent = PythonDesignerComponentFactory.CreateDesignerComponent(component);
if (designerComponent.IsSited) {
designerComponent.AppendCreateInstance(codeBuilder);
designerComponent.AppendCreateChildComponents(codeBuilder);
}
}
}
/// <summary>
/// Returns the sited components in the collection. If an object in the collection is not
/// an IComponent then this is added to the collection.
/// </summary>
static ICollection GetSitedComponentsAndNonComponents(ICollection components)
{
List<object> sitedComponents = new List<object>();
foreach (object obj in components) {
IComponent component = obj as IComponent;
if (component == null || IsSitedComponent(component)) {
sitedComponents.Add(obj);
}
}
return sitedComponents.ToArray();
}
static void AppendSystemArray(PythonCodeBuilder codeBuilder, string componentName, string methodName, string typeName, ICollection components)
{
if (components.Count > 0) {
codeBuilder.AppendIndentedLine("self._" + componentName + "." + methodName + "(System.Array[" + typeName + "](");
codeBuilder.IncreaseIndent();
int i = 0;
foreach (object component in components) {
if (i == 0) {
codeBuilder.AppendIndented("[");
} else {
codeBuilder.Append(",");
codeBuilder.AppendLine();
codeBuilder.AppendIndented(String.Empty);
}
if (component is IComponent) {
codeBuilder.Append("self._" + ((IComponent)component).Site.Name);
} else if (component is String) {
codeBuilder.Append(PythonPropertyValueAssignment.ToString(component));
} else {
codeBuilder.Append(GetVariableName(component, i + 1));
}
++i;
}
codeBuilder.Append("]))");
codeBuilder.AppendLine();
codeBuilder.DecreaseIndent();
}
}
}
}

36
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerComponentFactory.cs

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
// <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 ICSharpCode.PythonBinding
{
public class PythonDesignerComponentFactory
{
PythonDesignerComponentFactory()
{
}
/// <summary>
/// Creates a PythonDesignerComponent class for the specified component.
/// </summary>
public static PythonDesignerComponent CreateDesignerComponent(IComponent component)
{
if (component is ListView) {
return new PythonListViewComponent(component);
}
return new PythonDesignerComponent(component);
}
public static PythonDesignerComponent CreateDesignerRootComponent(IComponent component)
{
return new PythonDesignerRootComponent(component);
}
}
}

49
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerRootComponent.cs

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
// <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;
namespace ICSharpCode.PythonBinding
{
/// <summary>
/// Represents a root component in the designer.
/// </summary>
public class PythonDesignerRootComponent : PythonDesignerComponent
{
public PythonDesignerRootComponent(IComponent component)
: base(component)
{
}
public override string GetPropertyOwnerName()
{
return "self";
}
public override void AppendSuspendLayout(PythonCodeBuilder codeBuilder)
{
AppendMethodCalls(codeBuilder, suspendLayoutMethods);
}
public override void AppendResumeLayout(PythonCodeBuilder codeBuilder)
{
AppendMethodCalls(codeBuilder, resumeLayoutMethods);
}
public override void AppendComponent(PythonCodeBuilder codeBuilder)
{
// Add the child component's first.
foreach (IComponent component in GetChildComponents()) {
PythonDesignerComponentFactory.CreateDesignerComponent(component).AppendComponent(codeBuilder);
}
// Add root component
AppendComponentProperties(codeBuilder, false, false, true);
}
}
}

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

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
// <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 ICSharpCode.PythonBinding
{
/// <summary>
/// Used to generate code for a ListView component currently being designed.
/// </summary>
public class PythonListViewComponent : PythonDesignerComponent
{
public PythonListViewComponent(IComponent component) : base(component)
{
}
/// <summary>
/// Appends code that creates an instance of the list view.
/// </summary>
public override void AppendCreateInstance(PythonCodeBuilder codeBuilder)
{
// Append list view item creation first.
int count = 1;
foreach (ListViewItem item in GetListViewItems(Component)) {
AppendObjectCreation(codeBuilder, item, count, GetConstructorParameters(item));
++count;
}
// Append list view creation.
base.AppendCreateInstance(codeBuilder);
}
/// <summary>
/// Appends the component's properties.
/// </summary>
public override void AppendComponent(PythonCodeBuilder codeBuilder)
{
AppendComment(codeBuilder);
AppendListViewItemProperties(codeBuilder);
AppendComponentProperties(codeBuilder);
AppendChildComponentProperties(codeBuilder);
}
/// <summary>
/// Gets the parameters to the ListViewItem constructor.
/// </summary>
/// <remarks>
/// The constructors that are used:
/// ListViewItem()
/// ListViewItem(String text)
/// ListViewItem(string[] subItems)
/// </remarks>
object[] GetConstructorParameters(ListViewItem item)
{
if (String.IsNullOrEmpty(item.Text)) {
return new object[0];
}
return new object[] {item.Text};
}
static ListView.ListViewItemCollection GetListViewItems(IComponent component)
{
ListView listView = (ListView)component;
return listView.Items;
}
void AppendListViewItemProperties(PythonCodeBuilder codeBuilder)
{
int count = 1;
foreach (ListViewItem item in GetListViewItems(Component)) {
AppendObjectProperties(codeBuilder, item, count);
++count;
}
}
}
}

45
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/CreateDesignerComponentTests.cs

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
// <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.Windows.Forms;
using ICSharpCode.PythonBinding;
using NUnit.Framework;
namespace PythonBinding.Tests.Designer
{
/// <summary>
/// Tests the PythonControl's CreateDesignerComponent method.
/// </summary>
[TestFixture]
public class CreateDesignerComponentTests
{
[Test]
public void ListViewComponent()
{
using (ListView listView = new ListView()) {
Assert.IsInstanceOfType(typeof(PythonListViewComponent), PythonDesignerComponentFactory.CreateDesignerComponent(listView));
}
}
[Test]
public void TextBoxComponent()
{
using (TextBox textBox = new TextBox()) {
Assert.IsInstanceOfType(typeof(PythonDesignerComponent), PythonDesignerComponentFactory.CreateDesignerComponent(textBox));
}
}
[Test]
public void CreateRootDesigner()
{
using (TextBox textBox = new TextBox()) {
Assert.IsInstanceOfType(typeof(PythonDesignerRootComponent), PythonDesignerComponentFactory.CreateDesignerRootComponent(textBox));
}
}
}
}

12
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/FindAddRangeMethodTests.cs

@ -27,7 +27,7 @@ namespace PythonBinding.Tests.Designer @@ -27,7 +27,7 @@ namespace PythonBinding.Tests.Designer
MethodInfo expectedMethodInfo = FindMethod(menuStrip.Items, "AddRange", typeof(ToolStripItem[]));
Assert.IsNotNull(expectedMethodInfo);
Assert.AreSame(expectedMethodInfo, PythonControl.GetAddRangeSerializationMethod(menuStrip.Items));
Assert.AreSame(expectedMethodInfo, PythonDesignerComponent.GetAddRangeSerializationMethod(menuStrip.Items));
}
}
@ -36,7 +36,7 @@ namespace PythonBinding.Tests.Designer @@ -36,7 +36,7 @@ namespace PythonBinding.Tests.Designer
{
using (MenuStrip menuStrip = new MenuStrip()) {
MethodInfo methodInfo = FindMethod(menuStrip.Items, "AddRange", typeof(ToolStripItem[]));
Assert.AreEqual(typeof(ToolStripItem), PythonControl.GetArrayParameterType(methodInfo));
Assert.AreEqual(typeof(ToolStripItem), PythonDesignerComponent.GetArrayParameterType(methodInfo));
}
}
@ -44,13 +44,13 @@ namespace PythonBinding.Tests.Designer @@ -44,13 +44,13 @@ namespace PythonBinding.Tests.Designer
public void GetArrayParameterTypeFromMethodWithNoParameters()
{
MethodInfo methodInfo = typeof(String).GetMethod("Clone");
Assert.IsNull(PythonControl.GetArrayParameterType(methodInfo));
Assert.IsNull(PythonDesignerComponent.GetArrayParameterType(methodInfo));
}
[Test]
public void GetArrayParameterTypeWithNullMethodInfo()
{
Assert.IsNull(PythonControl.GetArrayParameterType(null));
Assert.IsNull(PythonDesignerComponent.GetArrayParameterType(null));
}
/// <summary>
@ -61,7 +61,7 @@ namespace PythonBinding.Tests.Designer @@ -61,7 +61,7 @@ namespace PythonBinding.Tests.Designer
public void FormControlsAddRangeMethodNotFound()
{
using (Form form = new Form()) {
Assert.IsNull(PythonControl.GetAddRangeSerializationMethod(form.Controls));
Assert.IsNull(PythonDesignerComponent.GetAddRangeSerializationMethod(form.Controls));
}
}
@ -72,7 +72,7 @@ namespace PythonBinding.Tests.Designer @@ -72,7 +72,7 @@ namespace PythonBinding.Tests.Designer
MethodInfo expectedMethodInfo = FindMethod(form.Controls, "Add", typeof(Control));
Assert.IsNotNull(expectedMethodInfo);
Assert.AreSame(expectedMethodInfo, PythonControl.GetAddSerializationMethod(form.Controls));
Assert.AreSame(expectedMethodInfo, PythonDesignerComponent.GetAddSerializationMethod(form.Controls));
}
}

4
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateAcceptButtonFormTestFixture.cs

@ -51,8 +51,8 @@ namespace PythonBinding.Tests.Designer @@ -51,8 +51,8 @@ namespace PythonBinding.Tests.Designer
PythonControl pythonForm = new PythonControl(" ");
generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form);
formChildComponents = PythonControl.GetChildComponents(form);
buttonChildComponents = PythonControl.GetChildComponents(button);
formChildComponents = PythonDesignerComponentFactory.CreateDesignerComponent(form).GetChildComponents();
buttonChildComponents = PythonDesignerComponentFactory.CreateDesignerComponent(button).GetChildComponents();
}
}

172
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateListViewItemTestFixture.cs

@ -22,9 +22,14 @@ namespace PythonBinding.Tests.Designer @@ -22,9 +22,14 @@ namespace PythonBinding.Tests.Designer
public class GenerateListViewItemsFormTestFixture
{
string generatedPythonCode;
object[] listViewChildren;
ListViewItem listViewItem1;
ListViewItem listViewItem2;
string createListViewCode;
string createListViewChildComponentsCode;
string suspendLayoutCode;
string resumeLayoutCode;
string listViewPropertiesCode;
object[] listViewChildComponents;
ColumnHeader columnHeader1;
ColumnHeader columnHeader2;
[TestFixtureSetUp]
public void SetUpFixture()
@ -47,23 +52,70 @@ namespace PythonBinding.Tests.Designer @@ -47,23 +52,70 @@ namespace PythonBinding.Tests.Designer
descriptors = TypeDescriptor.GetProperties(listView);
PropertyDescriptor descriptor = descriptors.Find("UseCompatibleStateImageBehavior", false);
descriptor.SetValue(listView, true);
descriptor = descriptors.Find("View", false);
descriptor.SetValue(listView, View.Details);
form.Controls.Add(listView);
// Add column headers.
columnHeader1 = (ColumnHeader)host.CreateComponent(typeof(ColumnHeader), "columnHeader1");
descriptors = TypeDescriptor.GetProperties(columnHeader1);
descriptor = descriptors.Find("Text", false);
descriptor.SetValue(columnHeader1, "columnHeader1");
listView.Columns.Add(columnHeader1);
columnHeader2 = (ColumnHeader)host.CreateComponent(typeof(ColumnHeader), "columnHeader2");
descriptors = TypeDescriptor.GetProperties(columnHeader2);
descriptor = descriptors.Find("Text", false);
descriptor.SetValue(columnHeader2, "columnHeader2");
listView.Columns.Add(columnHeader2);
// Add list view items.
ListViewItem item = new ListViewItem("aaa");
item.ToolTipText = "tooltip";
listView.Items.Add(item);
ListViewItem item2 = new ListViewItem("bbb");
listView.Items.Add(item2);
ListViewItem item3 = new ListViewItem();
listView.Items.Add(item3);
PythonControl pythonForm = new PythonControl(" ");
generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form);
listViewChildren = PythonControl.GetChildComponents(listView);
if (listViewChildren != null && listViewChildren.Length > 1) {
listViewItem1 = listViewChildren[0] as ListViewItem;
listViewItem2 = listViewChildren[1] as ListViewItem;
}
// Get list view creation code.
PythonCodeBuilder codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = " ";
PythonListViewComponent listViewComponent = new PythonListViewComponent(listView);
listViewComponent.AppendCreateInstance(codeBuilder);
createListViewCode = codeBuilder.ToString();
// Get list view child component's creation code.
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = " ";
listViewComponent.AppendCreateChildComponents(codeBuilder);
createListViewChildComponentsCode = codeBuilder.ToString();
// Get list view suspend layout code.
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = " ";
listViewComponent.AppendSuspendLayout(codeBuilder);
suspendLayoutCode = codeBuilder.ToString();
// Get generated list view property code.
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = " ";
codeBuilder.IncreaseIndent();
listViewComponent.AppendComponent(codeBuilder);
listViewPropertiesCode = codeBuilder.ToString();
// Get list view resume layout code.
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = " ";
listViewComponent.AppendResumeLayout(codeBuilder);
resumeLayoutCode = codeBuilder.ToString();
listViewChildComponents = listViewComponent.GetChildComponents();
}
}
@ -71,55 +123,131 @@ namespace PythonBinding.Tests.Designer @@ -71,55 +123,131 @@ namespace PythonBinding.Tests.Designer
public void GeneratedCode()
{
string expectedCode = "def InitializeComponent(self):\r\n" +
" listViewItem1 = System.Windows.Forms.ListViewItem(\"aaa\")\r\n" +
" listViewItem2 = System.Windows.Forms.ListViewItem(\"bbb\")\r\n" +
" listViewItem3 = System.Windows.Forms.ListViewItem()\r\n" +
" self._listView1 = System.Windows.Forms.ListView()\r\n" +
" listViewItem1 = System.Windows.Forms.ListViewItem()\r\n" +
" listViewItem2 = System.Windows.Forms.ListViewItem()\r\n" +
" self._columnHeader1 = System.Windows.Forms.ColumnHeader()\r\n" +
" self._columnHeader2 = System.Windows.Forms.ColumnHeader()\r\n" +
" self._listView1.SuspendLayout()\r\n" +
" self.SuspendLayout()\r\n" +
" # \r\n" +
" # listView1\r\n" +
" # \r\n" +
" listViewItem1.ToolTipText = \"tooltip\"\r\n" +
" self._listView1.Columns.AddRange(System.Array[System.Windows.Forms.ColumnHeader](\r\n" +
" [self._columnHeader1,\r\n" +
" self._columnHeader2]))\r\n" +
" self._listView1.Items.AddRange(System.Array[System.Windows.Forms.ListViewItem](\r\n" +
" [listViewItem1,\r\n" +
" listViewItem2]))\r\n" +
" listViewItem2,\r\n" +
" listViewItem3]))\r\n" +
" self._listView1.Location = System.Drawing.Point(0, 0)\r\n" +
" self._listView1.Name = \"listView1\"\r\n" +
" self._listView1.Size = System.Drawing.Size(204, 104)\r\n" +
" self._listView1.TabIndex = 0\r\n" +
" listViewItem1.ToolTipText = \"tooltip\"\r\n" +
" self._listView1.View = System.Windows.Forms.View.Details\r\n" +
" # \r\n" +
" # columnHeader1\r\n" +
" # \r\n" +
" self._columnHeader1.Text = \"columnHeader1\"\r\n" +
" # \r\n" +
" # columnHeader2\r\n" +
" # \r\n" +
" self._columnHeader2.Text = \"columnHeader2\"\r\n" +
" # \r\n" +
" # MainForm\r\n" +
" # \r\n" +
" self.ClientSize = System.Drawing.Size(200, 300)\r\n" +
" self.Controls.Add(self._listView1)\r\n" +
" self.Name = \"MainForm\"\r\n" +
" self._listView1.ResumeLayout(False)\r\n" +
" self._listView1.PerformLayout()\r\n" +
" self.ResumeLayout(False)\r\n" +
" self.PerformLayout()\r\n";
Assert.AreEqual(expectedCode, generatedPythonCode);
Assert.AreEqual(expectedCode, generatedPythonCode, generatedPythonCode);
}
/// <summary>
/// Should include the column header and list view item creation.
/// </summary>
[Test]
public void ListViewCreationCode()
{
string expectedCode = "listViewItem1 = System.Windows.Forms.ListViewItem(\"aaa\")\r\n" +
"listViewItem2 = System.Windows.Forms.ListViewItem(\"bbb\")\r\n" +
"listViewItem3 = System.Windows.Forms.ListViewItem()\r\n" +
"self._listView1 = System.Windows.Forms.ListView()\r\n";
Assert.AreEqual(expectedCode, createListViewCode);
}
[Test]
public void TwoListViewChildren()
public void TwoListViewChildComponents()
{
Assert.AreEqual(2, listViewChildren.Length);
Assert.AreEqual(2, listViewChildComponents.Length);
}
[Test]
public void ListViewItem1Text()
public void ListViewChildComponentAreColumnHeaders()
{
Assert.AreEqual("aaa", listViewItem1.Text);
object[] expectedChildComponents = new object[] {columnHeader1, columnHeader2};
Assert.AreEqual(expectedChildComponents, listViewChildComponents);
}
[Test]
public void ListViewItem1TooltipText()
public void SuspendLayoutGeneratedCode()
{
Assert.AreEqual("tooltip", listViewItem1.ToolTipText);
}
string expectedCode = "self._listView1.SuspendLayout()\r\n";
Assert.AreEqual(expectedCode, suspendLayoutCode);
}
[Test]
public void ListViewItem2Text()
public void ResumeLayoutGeneratedCode()
{
Assert.AreEqual("bbb", listViewItem2.Text);
string expectedCode = "self._listView1.ResumeLayout(False)\r\n" +
"self._listView1.PerformLayout()\r\n";
Assert.AreEqual(expectedCode, resumeLayoutCode);
}
[Test]
public void GeneratedListViewPropertiesCode()
{
string expectedCode = " # \r\n" +
" # listView1\r\n" +
" # \r\n" +
" listViewItem1.ToolTipText = \"tooltip\"\r\n" +
" self._listView1.Columns.AddRange(System.Array[System.Windows.Forms.ColumnHeader](\r\n" +
" [self._columnHeader1,\r\n" +
" self._columnHeader2]))\r\n" +
" self._listView1.Items.AddRange(System.Array[System.Windows.Forms.ListViewItem](\r\n" +
" [listViewItem1,\r\n" +
" listViewItem2,\r\n" +
" listViewItem3]))\r\n" +
" self._listView1.Location = System.Drawing.Point(0, 0)\r\n" +
" self._listView1.Name = \"listView1\"\r\n" +
" self._listView1.Size = System.Drawing.Size(204, 104)\r\n" +
" self._listView1.TabIndex = 0\r\n" +
" self._listView1.View = System.Windows.Forms.View.Details\r\n" +
" # \r\n" +
" # columnHeader1\r\n" +
" # \r\n" +
" self._columnHeader1.Text = \"columnHeader1\"\r\n" +
" # \r\n" +
" # columnHeader2\r\n" +
" # \r\n" +
" self._columnHeader2.Text = \"columnHeader2\"\r\n";
Assert.AreEqual(expectedCode, listViewPropertiesCode);
}
[Test]
public void ListViewChildComponentsCreated()
{
string expectedCode = "self._columnHeader1 = System.Windows.Forms.ColumnHeader()\r\n" +
"self._columnHeader2 = System.Windows.Forms.ColumnHeader()\r\n";
Assert.AreEqual(expectedCode, createListViewChildComponentsCode);
}
}
}

6
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateMenuStripItemsTestFixture.cs

@ -80,8 +80,8 @@ namespace PythonBinding.Tests.Designer @@ -80,8 +80,8 @@ namespace PythonBinding.Tests.Designer
PythonControl pythonForm = new PythonControl(" ");
generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form);
menuStripChildComponents = PythonControl.GetChildComponents(menuStrip);
fileMenuItemChildComponents = PythonControl.GetChildComponents(fileMenuItem);
menuStripChildComponents = PythonDesignerComponentFactory.CreateDesignerComponent(menuStrip).GetChildComponents();
fileMenuItemChildComponents = PythonDesignerComponentFactory.CreateDesignerComponent(fileMenuItem).GetChildComponents();
}
}
@ -145,7 +145,7 @@ namespace PythonBinding.Tests.Designer @@ -145,7 +145,7 @@ namespace PythonBinding.Tests.Designer
" self.ResumeLayout(False)\r\n" +
" self.PerformLayout()\r\n";
Assert.AreEqual(expectedCode, generatedPythonCode);
Assert.AreEqual(expectedCode, generatedPythonCode, generatedPythonCode);
}
[Test]

24
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateSimpleFormTestFixture.cs

@ -20,6 +20,8 @@ namespace PythonBinding.Tests.Designer @@ -20,6 +20,8 @@ namespace PythonBinding.Tests.Designer
public class GenerateSimpleFormTestFixture
{
string generatedPythonCode;
string formPropertiesCode;
string propertyOwnerName;
[TestFixtureSetUp]
public void SetUpFixture()
@ -36,6 +38,14 @@ namespace PythonBinding.Tests.Designer @@ -36,6 +38,14 @@ namespace PythonBinding.Tests.Designer
string indentString = " ";
PythonControl pythonForm = new PythonControl(indentString);
generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form);
PythonCodeBuilder codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
codeBuilder.IncreaseIndent();
PythonDesignerRootComponent designerRootComponent = new PythonDesignerRootComponent(form);
propertyOwnerName = designerRootComponent.GetPropertyOwnerName();
designerRootComponent.AppendComponentProperties(codeBuilder);
formPropertiesCode = codeBuilder.ToString();
}
}
@ -54,5 +64,19 @@ namespace PythonBinding.Tests.Designer @@ -54,5 +64,19 @@ namespace PythonBinding.Tests.Designer
Assert.AreEqual(expectedCode, generatedPythonCode);
}
[Test]
public void FormPropertiesCode()
{
string expectedCode = " self.ClientSize = System.Drawing.Size(284, 264)\r\n" +
" self.Name = \"MainForm\"\r\n";
Assert.AreEqual(expectedCode, formPropertiesCode);
}
[Test]
public void PropertyOwnerName()
{
Assert.AreEqual("self", propertyOwnerName);
}
}
}

94
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GenerateTextBoxFormTestFixture.cs

@ -20,6 +20,13 @@ namespace PythonBinding.Tests.Designer @@ -20,6 +20,13 @@ namespace PythonBinding.Tests.Designer
public class GenerateTextBoxFormTestFixture
{
string generatedPythonCode;
string textBoxPropertyCode;
string textBoxSuspendLayoutCode;
string textBoxResumeLayoutCode;
string textBoxCreationCode;
string textBoxPropertyOwnerName;
string suspendLayoutCode;
string resumeLayoutCode;
[TestFixtureSetUp]
public void SetUpFixture()
@ -43,6 +50,41 @@ namespace PythonBinding.Tests.Designer @@ -43,6 +50,41 @@ namespace PythonBinding.Tests.Designer
string indentString = " ";
PythonControl pythonForm = new PythonControl(indentString);
generatedPythonCode = pythonForm.GenerateInitializeComponentMethod(form);
PythonCodeBuilder codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
codeBuilder.IncreaseIndent();
PythonDesignerComponent designerComponent = new PythonDesignerComponent(textBox);
designerComponent.AppendComponent(codeBuilder);
textBoxPropertyCode = codeBuilder.ToString();
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
designerComponent.AppendCreateInstance(codeBuilder);
textBoxCreationCode = codeBuilder.ToString();
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
designerComponent.AppendSuspendLayout(codeBuilder);
textBoxSuspendLayoutCode = codeBuilder.ToString();
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
designerComponent.AppendResumeLayout(codeBuilder);
textBoxResumeLayoutCode = codeBuilder.ToString();
textBoxPropertyOwnerName = designerComponent.GetPropertyOwnerName();
PythonDesignerRootComponent designerRootComponent = new PythonDesignerRootComponent(form);
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
designerRootComponent.AppendSuspendLayout(codeBuilder);
suspendLayoutCode = codeBuilder.ToString();
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = indentString;
designerRootComponent.AppendResumeLayout(codeBuilder);
resumeLayoutCode = codeBuilder.ToString();
}
}
@ -70,5 +112,57 @@ namespace PythonBinding.Tests.Designer @@ -70,5 +112,57 @@ namespace PythonBinding.Tests.Designer
Assert.AreEqual(expectedCode, generatedPythonCode);
}
[Test]
public void TextBoxGeneratedCode()
{
string expectedCode = " # \r\n" +
" # textBox1\r\n" +
" # \r\n" +
" self._textBox1.Location = System.Drawing.Point(10, 10)\r\n" +
" self._textBox1.Name = \"textBox1\"\r\n" +
" self._textBox1.Size = System.Drawing.Size(110, 20)\r\n" +
" self._textBox1.TabIndex = 1\r\n";
Assert.AreEqual(expectedCode, textBoxPropertyCode);
}
[Test]
public void SuspendLayoutCodeNotGenerated()
{
Assert.AreEqual(String.Empty, textBoxSuspendLayoutCode);
}
[Test]
public void ResumeLayoutCodeNotGenerated()
{
Assert.AreEqual(String.Empty, textBoxResumeLayoutCode);
}
[Test]
public void TextBoxCreationCode()
{
string expectedCode = "self._textBox1 = System.Windows.Forms.TextBox()\r\n";
Assert.AreEqual(expectedCode, textBoxCreationCode);
}
[Test]
public void TextBoxPropertyOwnerName()
{
Assert.AreEqual("self._textBox1", textBoxPropertyOwnerName);
}
[Test]
public void SuspendLayoutCode()
{
Assert.AreEqual("self.SuspendLayout()\r\n", suspendLayoutCode);
}
[Test]
public void ResumeLayoutCode()
{
string expectedCode = "self.ResumeLayout(False)\r\n" +
"self.PerformLayout()\r\n";
Assert.AreEqual(expectedCode, resumeLayoutCode);
}
}
}

2
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GetSerializableContentPropertiesTestFixture.cs

@ -27,7 +27,7 @@ namespace PythonBinding.Tests.Designer @@ -27,7 +27,7 @@ namespace PythonBinding.Tests.Designer
using (Form form = new Form()) {
// Modify Form.Text so it is identified as needing serialization.
form.Text = "abc";
properties = PythonControl.GetSerializableContentProperties(form);
properties = PythonDesignerComponent.GetSerializableContentProperties(form);
}
}

2
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/IgnoreDesignTimePropertiesTestFixture.cs

@ -56,7 +56,7 @@ namespace PythonBinding.Tests.Designer @@ -56,7 +56,7 @@ namespace PythonBinding.Tests.Designer
PythonControl pythonForm = new PythonControl(" ");
generatedCode = pythonForm.GenerateInitializeComponentMethod(form);
propertyDescriptors = PythonControl.GetSerializableProperties(form);
propertyDescriptors = PythonDesignerComponent.GetSerializableProperties(form);
}
}

17
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/IsSitedComponentTests.cs

@ -19,13 +19,13 @@ namespace PythonBinding.Tests.Designer @@ -19,13 +19,13 @@ namespace PythonBinding.Tests.Designer
[Test]
public void NullComponent()
{
Assert.IsFalse(PythonControl.IsSitedComponent(null));
Assert.IsFalse(PythonDesignerComponent.IsSitedComponent(null));
}
[Test]
public void ComponentNotSited()
{
Assert.IsFalse(PythonControl.IsSitedComponent(new Component()));
Assert.IsFalse(PythonDesignerComponent.IsSitedComponent(new Component()));
}
[Test]
@ -33,13 +33,22 @@ namespace PythonBinding.Tests.Designer @@ -33,13 +33,22 @@ namespace PythonBinding.Tests.Designer
{
Component component = new Component();
component.Site = this;
Assert.IsTrue(PythonControl.IsSitedComponent(component));
Assert.IsTrue(PythonDesignerComponent.IsSitedComponent(component));
}
[Test]
public void SitedDesignerComponent()
{
Component component = new Component();
component.Site = this;
PythonDesignerComponent designerComponent = new PythonDesignerComponent(component);
Assert.IsTrue(designerComponent.IsSited);
}
[Test]
public void NonComponent()
{
Assert.IsFalse(PythonControl.IsSitedComponent(String.Empty));
Assert.IsFalse(PythonDesignerComponent.IsSitedComponent(String.Empty));
}
public IComponent Component {

76
src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonCodeBuilderTests.cs

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
// <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 ICSharpCode.PythonBinding;
using NUnit.Framework;
namespace PythonBinding.Tests.Designer
{
[TestFixture]
public class PythonCodeBuilderTests
{
PythonCodeBuilder codeBuilder;
[SetUp]
public void Init()
{
codeBuilder = new PythonCodeBuilder();
codeBuilder.IndentString = "\t";
}
[Test]
public void AppendNewLine()
{
codeBuilder.AppendLine();
Assert.AreEqual("\r\n", codeBuilder.ToString());
}
[Test]
public void AppendText()
{
codeBuilder.Append("abc");
Assert.AreEqual("abc", codeBuilder.ToString());
}
[Test]
public void AppendIndentedText()
{
codeBuilder.IncreaseIndent();
codeBuilder.AppendIndented("abc");
Assert.AreEqual("\tabc", codeBuilder.ToString());
}
[Test]
public void IncreaseIndentTwice()
{
codeBuilder.IncreaseIndent();
codeBuilder.IncreaseIndent();
codeBuilder.AppendIndented("abc");
Assert.AreEqual("\t\tabc", codeBuilder.ToString());
}
[Test]
public void DecreaseIndent()
{
codeBuilder.IncreaseIndent();
codeBuilder.AppendIndented("abc");
codeBuilder.AppendLine();
codeBuilder.DecreaseIndent();
codeBuilder.AppendIndented("abc");
Assert.AreEqual("\tabc\r\nabc", codeBuilder.ToString());
}
[Test]
public void AppendIndentedLine()
{
codeBuilder.IncreaseIndent();
codeBuilder.AppendIndentedLine("abc");
Assert.AreEqual("\tabc\r\n", codeBuilder.ToString());
}
}
}

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

@ -145,6 +145,7 @@ @@ -145,6 +145,7 @@
<Compile Include="Converter\VBClassConversionTestFixture.cs" />
<Compile Include="Converter\VBStringConcatTestFixture.cs" />
<Compile Include="Converter\WhileLoopConversionTestFixture.cs" />
<Compile Include="Designer\CreateDesignerComponentTests.cs" />
<Compile Include="Designer\CursorTypeResolutionTestFixture.cs" />
<Compile Include="Designer\DeserializeAssignmentTestFixtureBase.cs" />
<Compile Include="Designer\DeserializeColorFromArgbTestFixture.cs" />
@ -210,6 +211,7 @@ @@ -210,6 +211,7 @@
<Compile Include="Designer\OneCompatibleMethodTestFixture.cs" />
<Compile Include="Designer\PythonBaseClassTests.cs" />
<Compile Include="Designer\PythonCodeDeserializerTests.cs" />
<Compile Include="Designer\PythonCodeBuilderTests.cs" />
<Compile Include="Designer\PythonControlFieldExpressionTests.cs" />
<Compile Include="Designer\PythonGeneratorTestFixture.cs" />
<Compile Include="Designer\IsFormDesignableTestFixture.cs" />

8
src/AddIns/BackendBindings/Python/PythonBinding/Test/TODO.txt

@ -25,7 +25,6 @@ def main(args): @@ -25,7 +25,6 @@ def main(args):
print "Hello, World!"
return 0
* Test python compiler task logging.
* CtrlSpaceHelper.AddUsing should be called in the PythonResolver when
the ExpressionContext is Importable.
@ -71,10 +70,6 @@ def main(args): @@ -71,10 +70,6 @@ def main(args):
code completion after the import is incorrect here. It needs to
show items that are in the System namespace.
* Python code converter.
More tests...
* The PythonDesignerGenerator inserts an event handler at the end
of the active document. This is not correct. It should insert it at the
end of the form class. The file could contain multiple classes and
@ -93,9 +88,6 @@ def main(args): @@ -93,9 +88,6 @@ def main(args):
Handle invalid event name.
Check that += operator used.
* Double clicking an event handler name in the property grid when it is already defined generates a new
event handler.
* ContextMenuStrip - designer does not generate the correct code.
* Look at fixing the compiled exe so it can be run from a different folder.

Loading…
Cancel
Save