Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4044 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
20 changed files with 1280 additions and 586 deletions
@ -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--; |
||||
} |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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)); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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()); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue