You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
380 lines
12 KiB
380 lines
12 KiB
// <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.CodeDom; |
|
using System.ComponentModel; |
|
using System.ComponentModel.Design; |
|
using System.ComponentModel.Design.Serialization; |
|
|
|
namespace ICSharpCode.PythonBinding |
|
{ |
|
/// <summary> |
|
/// Used to generate Python code after the form has been changed in the designer. |
|
/// </summary> |
|
public class PythonCodeDomSerializer |
|
{ |
|
PythonCodeBuilder codeBuilder; |
|
string indentString = String.Empty; |
|
string rootResourceName = String.Empty; |
|
IDesignerSerializationManager serializationManager; |
|
|
|
public PythonCodeDomSerializer() |
|
: this("\t") |
|
{ |
|
} |
|
|
|
public PythonCodeDomSerializer(string indentString) |
|
{ |
|
this.indentString = indentString; |
|
} |
|
|
|
public string GenerateInitializeComponentMethodBody(IDesignerHost host, IDesignerSerializationManager serializationManager) |
|
{ |
|
return GenerateInitializeComponentMethodBody(host, serializationManager, String.Empty); |
|
} |
|
|
|
public string GenerateInitializeComponentMethodBody(IDesignerHost host, IDesignerSerializationManager serializationManager, string rootNamespace) |
|
{ |
|
return GenerateInitializeComponentMethodBody(host, serializationManager, rootResourceName, 0); |
|
} |
|
|
|
public string GenerateInitializeComponentMethodBody(IDesignerHost host, IDesignerSerializationManager serializationManager, string rootNamespace, int initialIndent) |
|
{ |
|
codeBuilder = new PythonCodeBuilder(initialIndent); |
|
codeBuilder.IndentString = indentString; |
|
|
|
CodeMemberMethod method = FindInitializeComponentMethod(host, serializationManager); |
|
GetResourceRootName(rootNamespace, host.RootComponent); |
|
AppendStatements(method.Statements); |
|
|
|
return codeBuilder.ToString(); |
|
} |
|
|
|
CodeMemberMethod FindInitializeComponentMethod(IDesignerHost host, IDesignerSerializationManager serializationManager) |
|
{ |
|
this.serializationManager = serializationManager; |
|
object rootComponent = host.RootComponent; |
|
TypeCodeDomSerializer serializer = serializationManager.GetSerializer(rootComponent.GetType(), typeof(TypeCodeDomSerializer)) as TypeCodeDomSerializer; |
|
CodeTypeDeclaration typeDec = serializer.Serialize(serializationManager, rootComponent, host.Container.Components) as CodeTypeDeclaration; |
|
foreach (CodeTypeMember member in typeDec.Members) { |
|
CodeMemberMethod method = member as CodeMemberMethod; |
|
if (method != null) { |
|
if (method.Name == "InitializeComponent") { |
|
return method; |
|
} |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
void AppendStatements(CodeStatementCollection statements) |
|
{ |
|
foreach (CodeStatement statement in statements) { |
|
AppendStatement(statement); |
|
} |
|
} |
|
|
|
void AppendStatement(CodeStatement statement) |
|
{ |
|
if (statement is CodeExpressionStatement) { |
|
AppendExpressionStatement((CodeExpressionStatement)statement); |
|
} else if (statement is CodeCommentStatement) { |
|
AppendCommentStatement((CodeCommentStatement)statement); |
|
} else if (statement is CodeAssignStatement) { |
|
AppendAssignStatement((CodeAssignStatement)statement); |
|
} else if (statement is CodeVariableDeclarationStatement) { |
|
AppendVariableDeclarationStatement((CodeVariableDeclarationStatement)statement); |
|
} else if (statement is CodeAttachEventStatement) { |
|
AppendAttachEventStatement((CodeAttachEventStatement)statement); |
|
} else { |
|
Console.WriteLine("AppendStatement: " + statement.GetType().Name); |
|
} |
|
} |
|
|
|
void AppendExpressionStatement(CodeExpressionStatement statement) |
|
{ |
|
codeBuilder.AppendIndented(String.Empty); |
|
AppendExpression(statement.Expression); |
|
codeBuilder.AppendLine(); |
|
} |
|
|
|
void AppendCommentStatement(CodeCommentStatement statement) |
|
{ |
|
codeBuilder.AppendIndented(String.Empty); |
|
codeBuilder.Append("# "); |
|
codeBuilder.Append(statement.Comment.Text); |
|
codeBuilder.AppendLine(); |
|
} |
|
|
|
void AppendExpression(CodeExpression expression) |
|
{ |
|
if (expression is CodeMethodInvokeExpression) { |
|
AppendMethodInvokeExpression((CodeMethodInvokeExpression)expression); |
|
} else if (expression is CodePropertyReferenceExpression) { |
|
AppendPropertyReferenceExpression((CodePropertyReferenceExpression)expression); |
|
} else if (expression is CodeObjectCreateExpression) { |
|
AppendObjectCreateExpression((CodeObjectCreateExpression)expression); |
|
} else if (expression is CodePrimitiveExpression) { |
|
AppendPrimitiveExpression((CodePrimitiveExpression)expression); |
|
} else if (expression is CodeFieldReferenceExpression) { |
|
AppendFieldReferenceExpression((CodeFieldReferenceExpression)expression); |
|
} else if (expression is CodeThisReferenceExpression) { |
|
AppendThisReferenceExpression(); |
|
} else if (expression is CodeTypeReferenceExpression) { |
|
AppendTypeReferenceExpression((CodeTypeReferenceExpression)expression); |
|
} else if (expression is CodeArrayCreateExpression) { |
|
AppendArrayCreateExpression((CodeArrayCreateExpression)expression); |
|
} else if (expression is CodeVariableReferenceExpression) { |
|
AppendVariableReferenceExpression((CodeVariableReferenceExpression)expression); |
|
} else if (expression is CodeDelegateCreateExpression) { |
|
AppendDelegateCreateExpression((CodeDelegateCreateExpression)expression); |
|
} else if (expression is CodeCastExpression) { |
|
AppendCastExpression((CodeCastExpression)expression); |
|
} else if (expression is CodeBinaryOperatorExpression) { |
|
AppendBinaryOperatorExpression((CodeBinaryOperatorExpression)expression); |
|
} else { |
|
Console.WriteLine("AppendExpression: " + expression.GetType().Name); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Appends a method call (e.g. "self.SuspendLayout()"); |
|
/// </summary> |
|
void AppendMethodInvokeExpression(CodeMethodInvokeExpression expression) |
|
{ |
|
AppendMethodReferenceExpression(expression.Method); |
|
AppendParameters(expression.Parameters); |
|
} |
|
|
|
void AppendMethodReferenceExpression(CodeMethodReferenceExpression expression) |
|
{ |
|
AppendExpression(expression.TargetObject); |
|
codeBuilder.Append("."); |
|
codeBuilder.Append(expression.MethodName); |
|
} |
|
|
|
void AppendParameters(CodeExpressionCollection parameters) |
|
{ |
|
codeBuilder.Append("("); |
|
bool firstParameter = true; |
|
foreach (CodeExpression expression in parameters) { |
|
if (firstParameter) { |
|
firstParameter = false; |
|
} else { |
|
codeBuilder.Append(", "); |
|
} |
|
AppendExpression(expression); |
|
} |
|
codeBuilder.Append(")"); |
|
} |
|
|
|
void AppendAssignStatement(CodeAssignStatement statement) |
|
{ |
|
codeBuilder.AppendIndented(String.Empty); |
|
AppendExpression(statement.Left); |
|
codeBuilder.Append(" = "); |
|
AppendExpression(statement.Right); |
|
codeBuilder.AppendLine(); |
|
} |
|
|
|
void AppendPropertyReferenceExpression(CodePropertyReferenceExpression expression) |
|
{ |
|
AppendExpression(expression.TargetObject); |
|
codeBuilder.Append("."); |
|
codeBuilder.Append(expression.PropertyName); |
|
} |
|
|
|
void AppendObjectCreateExpression(CodeObjectCreateExpression expression) |
|
{ |
|
AppendTypeReference(expression.CreateType); |
|
AppendParameters(expression.Parameters); |
|
} |
|
|
|
/// <summary> |
|
/// Appends a constant (e.g. string or int). |
|
/// </summary> |
|
void AppendPrimitiveExpression(CodePrimitiveExpression expression) |
|
{ |
|
codeBuilder.Append(PythonPropertyValueAssignment.ToString(expression.Value)); |
|
} |
|
|
|
void AppendFieldReferenceExpression(CodeFieldReferenceExpression expression) |
|
{ |
|
AppendExpression(expression.TargetObject); |
|
codeBuilder.Append("."); |
|
if (expression.FieldName != null) { |
|
if (expression.TargetObject is CodeThisReferenceExpression) { |
|
if (!IsInherited(expression.FieldName)) { |
|
codeBuilder.Append("_"); |
|
} |
|
} |
|
codeBuilder.Append(expression.FieldName); |
|
} |
|
} |
|
|
|
void AppendThisReferenceExpression() |
|
{ |
|
codeBuilder.Append("self"); |
|
} |
|
|
|
void AppendTypeReferenceExpression(CodeTypeReferenceExpression expression) |
|
{ |
|
AppendTypeReference(expression.Type); |
|
} |
|
|
|
void AppendTypeReference(CodeTypeReference typeRef) |
|
{ |
|
string typeRefText = typeRef.BaseType.Replace('+', '.'); |
|
codeBuilder.Append(typeRefText); |
|
} |
|
|
|
/// <summary> |
|
/// Creates an array expression: |
|
/// |
|
/// (System.Array[System.Object](\r\n" + |
|
/// ["aaa", |
|
/// "bbb", |
|
/// "ccc\"])) |
|
/// </summary> |
|
void AppendArrayCreateExpression(CodeArrayCreateExpression expression) |
|
{ |
|
codeBuilder.Append("System.Array["); |
|
AppendTypeReference(expression.CreateType); |
|
codeBuilder.Append("]"); |
|
|
|
AppendInitializers(expression.Initializers); |
|
} |
|
|
|
/// <summary> |
|
/// Appends initializers for an array. |
|
/// </summary> |
|
void AppendInitializers(CodeExpressionCollection initalizers) |
|
{ |
|
codeBuilder.Append("("); |
|
codeBuilder.AppendLine(); |
|
codeBuilder.IncreaseIndent(); |
|
codeBuilder.AppendIndented("["); |
|
|
|
bool firstInitializer = true; |
|
foreach (CodeExpression expression in initalizers) { |
|
if (firstInitializer) { |
|
firstInitializer = false; |
|
} else { |
|
codeBuilder.Append(","); |
|
codeBuilder.AppendLine(); |
|
codeBuilder.AppendIndented(String.Empty); |
|
} |
|
AppendExpression(expression); |
|
} |
|
|
|
codeBuilder.Append("])"); |
|
codeBuilder.DecreaseIndent(); |
|
} |
|
|
|
/// <summary> |
|
/// Appends a local variable declaration. |
|
/// </summary> |
|
void AppendVariableDeclarationStatement(CodeVariableDeclarationStatement statement) |
|
{ |
|
if (statement.Name == "resources") { |
|
codeBuilder.AppendIndented("resources = System.Resources.ResourceManager(\""); |
|
codeBuilder.Append(rootResourceName); |
|
codeBuilder.Append("\", System.Reflection.Assembly.GetEntryAssembly())"); |
|
codeBuilder.AppendLine(); |
|
} else { |
|
codeBuilder.AppendIndented(statement.Name); |
|
codeBuilder.Append(" = "); |
|
AppendExpression(statement.InitExpression); |
|
codeBuilder.AppendLine(); |
|
} |
|
} |
|
|
|
void AppendVariableReferenceExpression(CodeVariableReferenceExpression expression) |
|
{ |
|
codeBuilder.Append(expression.VariableName); |
|
} |
|
|
|
void AppendAttachEventStatement(CodeAttachEventStatement statement) |
|
{ |
|
codeBuilder.AppendIndented(String.Empty); |
|
AppendExpression(statement.Event.TargetObject); |
|
codeBuilder.Append("."); |
|
codeBuilder.Append(statement.Event.EventName); |
|
|
|
codeBuilder.Append(" += "); |
|
|
|
AppendExpression(statement.Listener); |
|
|
|
codeBuilder.AppendLine(); |
|
} |
|
|
|
void AppendDelegateCreateExpression(CodeDelegateCreateExpression expression) |
|
{ |
|
AppendExpression(expression.TargetObject); |
|
codeBuilder.Append("."); |
|
codeBuilder.Append(expression.MethodName); |
|
} |
|
|
|
void GetResourceRootName(string rootNamespace, IComponent component) |
|
{ |
|
rootResourceName = component.Site.Name; |
|
if (!String.IsNullOrEmpty(rootNamespace)) { |
|
rootResourceName = rootNamespace + "." + rootResourceName; |
|
} |
|
} |
|
|
|
void AppendCastExpression(CodeCastExpression expression) |
|
{ |
|
AppendExpression(expression.Expression); |
|
} |
|
|
|
bool IsInherited(string componentName) |
|
{ |
|
return IsInherited(serializationManager.GetInstance(componentName)); |
|
} |
|
|
|
static bool IsInherited(object component) |
|
{ |
|
InheritanceAttribute attribute = GetInheritanceAttribute(component); |
|
if (attribute != null) { |
|
return attribute.InheritanceLevel != InheritanceLevel.NotInherited; |
|
} |
|
return false; |
|
} |
|
|
|
static InheritanceAttribute GetInheritanceAttribute(object component) |
|
{ |
|
if (component != null) { |
|
AttributeCollection attributes = TypeDescriptor.GetAttributes(component); |
|
return attributes[typeof(InheritanceAttribute)] as InheritanceAttribute; |
|
} |
|
return null; |
|
} |
|
|
|
/// <summary> |
|
/// Appends expressions like "AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top" |
|
/// </summary> |
|
void AppendBinaryOperatorExpression(CodeBinaryOperatorExpression expression) |
|
{ |
|
AppendExpression(expression.Left); |
|
AppendBinaryOperator(expression.Operator); |
|
AppendExpression(expression.Right); |
|
} |
|
|
|
void AppendBinaryOperator(CodeBinaryOperatorType operatorType) |
|
{ |
|
codeBuilder.Append(" "); |
|
switch (operatorType) { |
|
case CodeBinaryOperatorType.BitwiseOr: |
|
codeBuilder.Append("|"); |
|
break; |
|
} |
|
codeBuilder.Append(" "); |
|
} |
|
} |
|
}
|
|
|