diff options
author | Iain McCoy <iainmc@mono-cvs.ximian.com> | 2005-08-28 14:15:04 +0400 |
---|---|---|
committer | Iain McCoy <iainmc@mono-cvs.ximian.com> | 2005-08-28 14:15:04 +0400 |
commit | 0347254997968dfdae758ea9c9062b933f1c9cfc (patch) | |
tree | 73e9f2be9b9cb833444ed87d71c7580906b6d416 /mcs/class | |
parent | d88c2074f3304074083964eb8c52b1730a449905 (diff) |
2005-08-28 Iain McCoy <iain@mccoy.id.au>
* Mono.Windows.Serialization/ParserConsumerBase.cs: move dispatching
to handlers based on nodes returned from the parser into a base class
* Mono.Windows.Serialization/ParserToCode.cs: use ParserConsumerBase
* System.Windows.Serialization/Parser.cs: use ParserConsumerBase,
added support for objects as values of dependency properties
* demo/runtimetest.xaml: added a demonstration of objects as values of
dependency properties
svn path=/trunk/mcs/; revision=49019
Diffstat (limited to 'mcs/class')
5 files changed, 626 insertions, 649 deletions
diff --git a/mcs/class/PresentationFramework/ChangeLog b/mcs/class/PresentationFramework/ChangeLog index 630f4790b3d..980ce218bd4 100644 --- a/mcs/class/PresentationFramework/ChangeLog +++ b/mcs/class/PresentationFramework/ChangeLog @@ -1,3 +1,11 @@ +2005-08-28 Iain McCoy <iain@mccoy.id.au> + + * Mono.Windows.Serialization/ParserConsumerBase.cs: move dispatching + to handlers based on nodes returned from the parser into a base class + * Mono.Windows.Serialization/ParserToCode.cs: use ParserConsumerBase + * System.Windows.Serialization/Parser.cs: use ParserConsumerBase, + support for objects as values of dependency properties + 2005-08-27 Iain McCoy <iain@mccoy.id.au> * Mono.Windows.Serialization/XamlParser.cs: added support for objects diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/ParserConsumerBase.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/ParserConsumerBase.cs new file mode 100644 index 00000000000..cc334af1982 --- /dev/null +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/ParserConsumerBase.cs @@ -0,0 +1,126 @@ +using System; +using System.Reflection; +using System.Windows; +using System.Windows.Serialization; +using System.Xml; +using System.Diagnostics; + +namespace Mono.Windows.Serialization { + internal abstract class ParserConsumerBase { + internal void crunch (XmlTextReader reader) { + int justClosed = 0; + XamlParser p = new XamlParser(reader); + XamlNode n; + while (true) { + n = p.GetNextNode(); + if (n == null) + break; + Debug.WriteLine(this.GetType() + ": INCOMING " + n.GetType()); + if (n is XamlDocumentStartNode) { + Debug.WriteLine(this.GetType() + ": document begins"); + // do nothing + } else if (n is XamlElementStartNode && n.Depth == 0) { + Debug.WriteLine(this.GetType() + ": element begins as top-level"); + CreateTopLevel(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); + } else if (n is XamlElementStartNode && ((XamlElementStartNode)n).propertyObject) { + Debug.WriteLine(this.GetType() + ": element begins as property value"); + CreatePropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); + } else if (n is XamlElementStartNode && ((XamlElementStartNode)n).depPropertyObject) { + Debug.WriteLine(this.GetType() + ": element begins as dependency property value"); + CreateDependencyPropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); + + } else if (n is XamlElementStartNode) { + Debug.WriteLine(this.GetType() + ": element begins"); + CreateObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); + } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).PropInfo != null) { + Debug.WriteLine(this.GetType() + ": normal property begins"); + CreateProperty(((XamlPropertyNode)n).PropInfo); + } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).DP != null) { + Debug.WriteLine(this.GetType() + ": dependency property begins"); + DependencyProperty dp = ((XamlPropertyNode)n).DP; + Type typeAttachedTo = dp.OwnerType; + string propertyName = ((XamlPropertyNode)n).PropertyName; + + CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType); + } else if (n is XamlClrEventNode && !(((XamlClrEventNode)n).EventMember is EventInfo)) { + Debug.WriteLine(this.GetType() + ": delegate property"); + CreatePropertyDelegate(((XamlClrEventNode)n).Value, ((PropertyInfo)((XamlClrEventNode)n).EventMember).PropertyType); + EndProperty(); + + + } else if (n is XamlClrEventNode) { + Debug.WriteLine(this.GetType() + ": event"); + CreateEvent((EventInfo)((XamlClrEventNode)n).EventMember); + CreateEventDelegate(((XamlClrEventNode)n).Value, ((EventInfo)((XamlClrEventNode)n).EventMember).EventHandlerType); + EndEvent(); + + } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Object){ + Debug.WriteLine(this.GetType() + ": text for object"); + CreateObjectText(((XamlTextNode)n).TextContent); + } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Property){ + Debug.WriteLine(this.GetType() + ": text for property"); + CreatePropertyText(((XamlTextNode)n).TextContent, ((XamlTextNode)n).finalType); + EndProperty(); + } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.DependencyProperty){ + Debug.WriteLine(this.GetType() + ": text for dependency property"); + CreateDependencyPropertyText(((XamlTextNode)n).TextContent, ((XamlTextNode)n).finalType); + EndDependencyProperty(); + } else if (n is XamlPropertyComplexEndNode) { + Debug.WriteLine(this.GetType() + ": end complex property"); + if (justClosed == 2) { + EndProperty(); + } else if (justClosed == 1) { + EndDependencyProperty(); + } else { + throw new NotImplementedException("justClosed of " + justClosed); + } + justClosed = 0; + } else if (n is XamlLiteralContentNode) { + Debug.WriteLine(this.GetType() + ": literal content"); + CreateCode(((XamlLiteralContentNode)n).Content); + } else if (n is XamlElementEndNode) { + Debug.WriteLine(this.GetType() + ": end element"); + Type ft = ((XamlElementEndNode)n).finalType; + if (((XamlElementEndNode)n).propertyObject) { + EndPropertyObject(ft); + justClosed = 2; + } else if (((XamlElementEndNode)n).depPropertyObject) { + EndDependencyPropertyObject(ft); + justClosed = 1; + } else { + EndObject(); + } + } else if (n is XamlDocumentEndNode) { + Debug.WriteLine(this.GetType() + ": end document"); + Finish(); + } else { + throw new Exception("Unknown node " + n.GetType()); + } + } + + } + + + public abstract void CreateTopLevel(Type parent, string className); + public abstract void CreateObject(Type type, string varName); + public abstract void CreateProperty(PropertyInfo property); + public abstract void CreateEvent(EventInfo evt); + public abstract void CreateDependencyProperty(Type attachedTo, string propertyName, Type propertyType); + public abstract void EndDependencyProperty(); + public abstract void CreateObjectText(string text); + public abstract void CreateEventDelegate(string functionName, Type eventDelegateType); + public abstract void CreatePropertyDelegate(string functionName, Type propertyType); + public abstract void CreatePropertyText(string text, Type propertyType); + public abstract void CreateDependencyPropertyText(string text, Type propertyType); + public abstract void CreateDependencyPropertyObject(Type type, string varName); + public abstract void CreatePropertyObject(Type type, string varName); + public abstract void EndDependencyPropertyObject(Type destType); + public abstract void EndPropertyObject(Type destType); + public abstract void EndObject(); + public abstract void EndProperty(); + public abstract void EndEvent(); + public abstract void CreateCode(string code); + public abstract void Finish(); + + } +} diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/ParserToCode.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/ParserToCode.cs index 146f5950eff..2c0e526948b 100644 --- a/mcs/class/PresentationFramework/Mono.Windows.Serialization/ParserToCode.cs +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/ParserToCode.cs @@ -39,479 +39,391 @@ using System.Windows; namespace Mono.Windows.Serialization { public class ParserToCode { - TextWriter writer; - ICodeGenerator generator; - bool isPartial; - - ArrayList objects = new ArrayList(); - Hashtable nameClashes = new Hashtable(); - int tempIndex = 0; - - CodeCompileUnit code; - CodeTypeDeclaration type; - CodeConstructor constructor; + private string result; private static readonly Type xamlParserType = typeof(XamlParser); public static string Parse(XmlTextReader reader, ICodeGenerator generator, bool isPartial) { ParserToCode cw = new ParserToCode(reader, generator, isPartial); - return ((StringWriter)cw.writer).ToString(); + return cw.result; } - // pushes: the code writer - private void init(ICodeGenerator generator, bool isPartial) + private ParserToCode(XmlTextReader reader, ICodeGenerator generator, bool isPartial) { - this.generator = generator; - this.isPartial = isPartial; - this.writer = new StringWriter(); - code = new CodeCompileUnit(); - push(code); + Consumer consumer = new Consumer(generator, isPartial); + consumer.crunch(reader); + result = ((StringWriter)consumer.writer).ToString(); } + private class Consumer : ParserConsumerBase { + public TextWriter writer; + ICodeGenerator generator; + bool isPartial; - private ParserToCode(XmlTextReader reader, ICodeGenerator generator, bool isPartial) - { - int justClosed = 0; - init(generator, isPartial); - XamlParser p = new XamlParser(reader); - XamlNode n; - while (true) { - n = p.GetNextNode(); - if (n == null) - break; - Debug.WriteLine("ParserToCode: INCOMING " + n.GetType()); - if (n is XamlDocumentStartNode) { - Debug.WriteLine("ParserToCode: document begins"); - // do nothing - } else if (n is XamlElementStartNode && n.Depth == 0) { - Debug.WriteLine("ParserToCode: element begins as top-level"); - CreateTopLevel(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); - } else if (n is XamlElementStartNode && ((XamlElementStartNode)n).propertyObject) { - Debug.WriteLine("ParserToCode: element begins as property value"); - CreatePropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); - } else if (n is XamlElementStartNode && ((XamlElementStartNode)n).depPropertyObject) { - Debug.WriteLine("ParserToCode: element begins as dependency property value"); - CreateDependencyPropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); - - } else if (n is XamlElementStartNode) { - Debug.WriteLine("ParserToCode: element begins"); - CreateObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); - } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).PropInfo != null) { - Debug.WriteLine("ParserToCode: normal property begins"); - CreateProperty(((XamlPropertyNode)n).PropInfo); - } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).DP != null) { - Debug.WriteLine("ParserToCode: dependency property begins"); - DependencyProperty dp = ((XamlPropertyNode)n).DP; - Type typeAttachedTo = dp.OwnerType; - string propertyName = ((XamlPropertyNode)n).PropertyName; - - CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType); - } else if (n is XamlClrEventNode && !(((XamlClrEventNode)n).EventMember is EventInfo)) { - Debug.WriteLine("ParserToCode: delegate property"); - CreatePropertyDelegate(((XamlClrEventNode)n).Value, ((PropertyInfo)((XamlClrEventNode)n).EventMember).PropertyType); - EndProperty(); - - - } else if (n is XamlClrEventNode) { - Debug.WriteLine("ParserToCode: event"); - CreateEvent((EventInfo)((XamlClrEventNode)n).EventMember); - CreateEventDelegate(((XamlClrEventNode)n).Value, ((EventInfo)((XamlClrEventNode)n).EventMember).EventHandlerType); - EndEvent(); - - } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Object){ - Debug.WriteLine("ParserToCode: text for object"); - CreateObjectText(((XamlTextNode)n).TextContent); - } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Property){ - Debug.WriteLine("ParserToCode: text for property"); - CreatePropertyText(((XamlTextNode)n).TextContent, ((XamlTextNode)n).finalType); - EndProperty(); - } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.DependencyProperty){ - Debug.WriteLine("ParserToCode: text for dependency property"); - CreateDependencyPropertyText(((XamlTextNode)n).TextContent, ((XamlTextNode)n).finalType); - EndDependencyProperty(); - } else if (n is XamlPropertyComplexEndNode) { - Debug.WriteLine("ParserToCode: end complex property"); - if (justClosed == 2) { - EndProperty(); - } else if (justClosed == 1) { - EndDependencyProperty(); - } else { - throw new NotImplementedException("justClosed of " + justClosed); - } - justClosed = 0; - } else if (n is XamlLiteralContentNode) { - Debug.WriteLine("ParserToCode: literal content"); - CreateCode(((XamlLiteralContentNode)n).Content); - } else if (n is XamlElementEndNode) { - Debug.WriteLine("ParserToCode: end element"); - Type ft = ((XamlElementEndNode)n).finalType; - if (((XamlElementEndNode)n).propertyObject) { - EndPropertyObject(ft); - justClosed = 2; - } else if (((XamlElementEndNode)n).depPropertyObject) { - EndDependencyPropertyObject(ft); - justClosed = 1; - } else { - EndObject(); - } - } else if (n is XamlDocumentEndNode) { - Debug.WriteLine("ParserToCode: end document"); - Finish(); + ArrayList objects = new ArrayList(); + Hashtable nameClashes = new Hashtable(); + int tempIndex = 0; + + CodeCompileUnit code; + CodeTypeDeclaration type; + CodeConstructor constructor; + + public Consumer(ICodeGenerator generator, bool isPartial) + { + this.generator = generator; + this.isPartial = isPartial; + this.writer = new StringWriter(); + } + // pushes: a CodeVariableReferenceExpression to the present + // instance + public override void CreateTopLevel(Type parent, string className) + { + debug(); + code = new CodeCompileUnit(); + push(code); + if (className == null) { + className = "derived" + parent.Name; + } + int endNamespaceName = className.LastIndexOf("."); + string clrNamespace; + if (endNamespaceName < 0) { + clrNamespace = "DefaultNamespace"; } else { - throw new Exception("Unknown node " + n.GetType()); + clrNamespace = className.Substring(0, + endNamespaceName); + className = className.Substring(endNamespaceName+1); } + CodeNamespace ns = new CodeNamespace(clrNamespace); + ((CodeCompileUnit)objects[0]).Namespaces.Add(ns); + + type = new CodeTypeDeclaration(className); + if (isPartial) { + #if NET_2_0 + type.IsPartial = isPartial; + #else + throw new Exception("Cannot create partial class"); + #endif + } + type.BaseTypes.Add(new CodeTypeReference(parent)); + constructor = new CodeConstructor(); + type.Members.Add(constructor); + ns.Types.Add(type); + + push(new CodeThisReferenceExpression()); } - } - + // bottom of stack holds CodeVariableReferenceExpression + // pushes a reference to the new current type + public override void CreateObject(Type type, string varName) + { + debug(); + bool isDefaultName; + if (varName == null) { + isDefaultName = true; + varName = Char.ToLower(type.Name[0]) + type.Name.Substring(1); + // make sure something sensible happens when class + // names start with a lowercase letter + if (varName == type.Name) + varName = "_" + varName; + } else { + isDefaultName = false; + } - // pushes: a CodeVariableReferenceExpression to the present - // instance - public void CreateTopLevel(Type parent, string className) - { - debug(); - if (className == null) { - className = "derived" + parent.Name; + if (isDefaultName) { + if (!nameClashes.ContainsKey(varName)) + nameClashes[varName] = 0; + + nameClashes[varName] = 1 + (int)nameClashes[varName]; + varName += (int)nameClashes[varName]; + } + + + if (isDefaultName) { + CodeVariableDeclarationStatement declaration = + new CodeVariableDeclarationStatement(type, + varName, + new CodeObjectCreateExpression(type)); + constructor.Statements.Add(declaration); + } else { + CodeMemberField declaration = new CodeMemberField(type, varName); + declaration.InitExpression = new CodeObjectCreateExpression(type); + this.type.Members.Add(declaration); + } + CodeVariableReferenceExpression varRef = new CodeVariableReferenceExpression(varName); + CodeMethodInvokeExpression addChild = new CodeMethodInvokeExpression( + (CodeExpression)peek(), + "AddChild", + varRef); + constructor.Statements.Add(addChild); + push(varRef); } - int endNamespaceName = className.LastIndexOf("."); - string clrNamespace; - if (endNamespaceName < 0) { - clrNamespace = "DefaultNamespace"; - } else { - clrNamespace = className.Substring(0, - endNamespaceName); - className = className.Substring(endNamespaceName+1); + + // top of stack is a reference to an object + // pushes a reference to the property + public override void CreateProperty(PropertyInfo property) + { + debug(); + CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression( + (CodeExpression)peek(), + property.Name); + push(prop); } - CodeNamespace ns = new CodeNamespace(clrNamespace); - ((CodeCompileUnit)objects[0]).Namespaces.Add(ns); - - type = new CodeTypeDeclaration(className); - if (isPartial) { -#if NET_2_0 - type.IsPartial = isPartial; -#else - throw new Exception("Cannot create partial class"); -#endif + + // top of stack is a reference to an object + // pushes a reference to the event + public override void CreateEvent(EventInfo evt) + { + debug(); + CodeEventReferenceExpression expr = new CodeEventReferenceExpression( + (CodeExpression)peek(), + evt.Name); + push(expr); } - type.BaseTypes.Add(new CodeTypeReference(parent)); - constructor = new CodeConstructor(); - type.Members.Add(constructor); - ns.Types.Add(type); - - push(new CodeThisReferenceExpression()); - } - // bottom of stack holds CodeVariableReferenceExpression - // pushes a reference to the new current type - public void CreateObject(Type type, string varName) - { - debug(); - bool isDefaultName; - if (varName == null) { - isDefaultName = true; - varName = Char.ToLower(type.Name[0]) + type.Name.Substring(1); - // make sure something sensible happens when class - // names start with a lowercase letter - if (varName == type.Name) - varName = "_" + varName; - } else { - isDefaultName = false; + // top of stack is a reference to an object + // pushes a reference to the expression that + // will set the property and a reference to + // the name of the temp variable to hold the + // property + public override void CreateDependencyProperty(Type attachedTo, string propertyName, Type propertyType) + { + debug(); + string varName = "temp"; + varName += tempIndex; + tempIndex += 1; + CodeVariableDeclarationStatement decl = new CodeVariableDeclarationStatement(propertyType, varName); + constructor.Statements.Add(decl); + + + CodeMethodInvokeExpression call = new CodeMethodInvokeExpression( + new CodeTypeReferenceExpression(attachedTo), + "Set" + propertyName, + (CodeExpression)peek(), + new CodeVariableReferenceExpression(varName)); + + push(call); + push(new CodeVariableReferenceExpression(varName)); } - if (isDefaultName) { - if (!nameClashes.ContainsKey(varName)) - nameClashes[varName] = 0; + // pops 2 items: the name of the property, and the object to attach to + public override void EndDependencyProperty() + { + debug(); + pop(); // pop the variable name - we don't need it since it's already baked into the call + CodeExpression call = (CodeExpression)pop(); + constructor.Statements.Add(call); + } - nameClashes[varName] = 1 + (int)nameClashes[varName]; - varName += (int)nameClashes[varName]; + // top of stack must be an object reference + public override void CreateObjectText(string text) + { + debug(); + CodeVariableReferenceExpression var = (CodeVariableReferenceExpression)peek(); + CodeMethodInvokeExpression call = new CodeMethodInvokeExpression( + var, + "AddText", + new CodePrimitiveExpression(text)); + constructor.Statements.Add(call); } + // top of stack is reference to an event + public override void CreateEventDelegate(string functionName, Type eventDelegateType) + { + debug(); + CodeExpression expr = new CodeObjectCreateExpression( + eventDelegateType, + new CodeMethodReferenceExpression( + new CodeThisReferenceExpression(), + functionName)); + CodeAttachEventStatement attach = new CodeAttachEventStatement( + (CodeEventReferenceExpression)peek(), + expr); + constructor.Statements.Add(attach); - if (isDefaultName) { - CodeVariableDeclarationStatement declaration = - new CodeVariableDeclarationStatement(type, - varName, - new CodeObjectCreateExpression(type)); - constructor.Statements.Add(declaration); - } else { - CodeMemberField declaration = new CodeMemberField(type, varName); - declaration.InitExpression = new CodeObjectCreateExpression(type); - this.type.Members.Add(declaration); } - CodeVariableReferenceExpression varRef = new CodeVariableReferenceExpression(varName); - CodeMethodInvokeExpression addChild = new CodeMethodInvokeExpression( - (CodeExpression)peek(), - "AddChild", - varRef); - constructor.Statements.Add(addChild); - push(varRef); - } + // top of stack is reference to a property + public override void CreatePropertyDelegate(string functionName, Type propertyType) + { + debug(); + CodeExpression expr = new CodeObjectCreateExpression( + propertyType, + new CodeMethodReferenceExpression( + new CodeThisReferenceExpression(), + functionName)); + CodeAssignStatement assignment = new CodeAssignStatement( + (CodeExpression)peek(), + expr); + constructor.Statements.Add(assignment); + } - // top of stack is a reference to an object - // pushes a reference to the property - public void CreateProperty(PropertyInfo property) - { - debug(); - CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression( - (CodeExpression)peek(), - property.Name); - push(prop); - } + private CodeExpression fetchConverter(Type propertyType) + { + return new CodeMethodInvokeExpression( + new CodeMethodReferenceExpression( + new CodeTypeReferenceExpression(typeof(System.ComponentModel.TypeDescriptor)), + "GetConverter"), + new CodeTypeOfExpression(propertyType)); + } - // top of stack is a reference to an object - // pushes a reference to the event - public void CreateEvent(EventInfo evt) - { - debug(); - CodeEventReferenceExpression expr = new CodeEventReferenceExpression( - (CodeExpression)peek(), - evt.Name); - push(expr); - } + // top of stack is reference to a property + public override void CreatePropertyText(string text, Type propertyType) + { + debug(); + CreateDependencyPropertyText(text, propertyType); + } + // top of stack is reference to an attached property + public override void CreateDependencyPropertyText(string text, Type propertyType) + { + debug(); + CodeExpression expr = new CodePrimitiveExpression(text); + if (propertyType != typeof(string)) { + expr = new CodeCastExpression( + new CodeTypeReference(propertyType), + new CodeMethodInvokeExpression( + fetchConverter(propertyType), + "ConvertFromString", + expr)); + } + CodeAssignStatement assignment = new CodeAssignStatement( + (CodeExpression)peek(), + expr); + + constructor.Statements.Add(assignment); + } - // top of stack is a reference to an object - // pushes a reference to the expression that - // will set the property and a reference to - // the name of the temp variable to hold the - // property - public void CreateDependencyProperty(Type attachedTo, string propertyName, Type propertyType) - { - debug(); - string varName = "temp"; - varName += tempIndex; - tempIndex += 1; - CodeVariableDeclarationStatement decl = new CodeVariableDeclarationStatement(propertyType, varName); - constructor.Statements.Add(decl); - - - CodeMethodInvokeExpression call = new CodeMethodInvokeExpression( - new CodeTypeReferenceExpression(attachedTo), - "Set" + propertyName, - (CodeExpression)peek(), - new CodeVariableReferenceExpression(varName)); - - push(call); - push(new CodeVariableReferenceExpression(varName)); - } + public override void CreateDependencyPropertyObject(Type type, string varName) + { + CreatePropertyObject(type, varName); + } - // pops 2 items: the name of the property, and the object to attach to - public void EndDependencyProperty() - { - debug(); - pop(); // pop the variable name - we don't need it since it's already baked into the call - CodeExpression call = (CodeExpression)pop(); - constructor.Statements.Add(call); - } + public override void CreatePropertyObject(Type type, string varName) + { + debug(); + bool isDefaultName; + if (varName == null) { + isDefaultName = true; + varName = Char.ToLower(type.Name[0]) + type.Name.Substring(1); + // make sure something sensible happens when class + // names start with a lowercase letter + if (varName == type.Name) + varName = "_" + varName; + } else { + isDefaultName = false; + } - // top of stack must be an object reference - public void CreateObjectText(string text) - { - debug(); - CodeVariableReferenceExpression var = (CodeVariableReferenceExpression)peek(); - CodeMethodInvokeExpression call = new CodeMethodInvokeExpression( - var, - "AddText", - new CodePrimitiveExpression(text)); - constructor.Statements.Add(call); - } + if (isDefaultName) { + if (!nameClashes.ContainsKey(varName)) + nameClashes[varName] = 0; + nameClashes[varName] = 1 + (int)nameClashes[varName]; + varName += (int)nameClashes[varName]; + } - // top of stack is reference to an event - public void CreateEventDelegate(string functionName, Type eventDelegateType) - { - debug(); - CodeExpression expr = new CodeObjectCreateExpression( - eventDelegateType, - new CodeMethodReferenceExpression( - new CodeThisReferenceExpression(), - functionName)); - CodeAttachEventStatement attach = new CodeAttachEventStatement( - (CodeEventReferenceExpression)peek(), - expr); - constructor.Statements.Add(attach); - } - // top of stack is reference to a property - public void CreatePropertyDelegate(string functionName, Type propertyType) - { - debug(); - CodeExpression expr = new CodeObjectCreateExpression( - propertyType, - new CodeMethodReferenceExpression( - new CodeThisReferenceExpression(), - functionName)); - CodeAssignStatement assignment = new CodeAssignStatement( - (CodeExpression)peek(), - expr); - constructor.Statements.Add(assignment); - } + if (isDefaultName) { + CodeVariableDeclarationStatement declaration = + new CodeVariableDeclarationStatement(type, + varName, + new CodeObjectCreateExpression(type)); + constructor.Statements.Add(declaration); + } else { + CodeMemberField declaration = new CodeMemberField(type, varName); + declaration.InitExpression = new CodeObjectCreateExpression(type); + this.type.Members.Add(declaration); + } + CodeVariableReferenceExpression varRef = new CodeVariableReferenceExpression(varName); - private CodeExpression fetchConverter(Type propertyType) - { - return new CodeMethodInvokeExpression( - new CodeMethodReferenceExpression( - new CodeTypeReferenceExpression(typeof(System.ComponentModel.TypeDescriptor)), - "GetConverter"), - new CodeTypeOfExpression(propertyType)); - } + push(type); + push(varRef); + + } - // top of stack is reference to a property - public void CreatePropertyText(string text, Type propertyType) - { - debug(); - CreateDependencyPropertyText(text, propertyType); - } - // top of stack is reference to an attached property - public void CreateDependencyPropertyText(string text, Type propertyType) - { - debug(); - CodeExpression expr = new CodePrimitiveExpression(text); - if (propertyType != typeof(string)) { - expr = new CodeCastExpression( - new CodeTypeReference(propertyType), - new CodeMethodInvokeExpression( - fetchConverter(propertyType), - "ConvertFromString", - expr)); + public override void EndDependencyPropertyObject(Type destType) + { + EndPropertyObject(destType); + } + public override void EndPropertyObject(Type destType) + { + debug(); + CodeExpression varRef = (CodeExpression)pop(); + Type sourceType = (Type)pop(); + + Debug.WriteLine("ParserToCode: " + destType + "->" + sourceType); + + + CodeExpression expr; + if (sourceType == destType || sourceType.IsSubclassOf(destType)) + expr = varRef; + else + expr = new CodeCastExpression( + new CodeTypeReference(destType), + new CodeMethodInvokeExpression( + fetchConverter(sourceType), + "ConvertTo", + varRef, + new CodeTypeOfExpression(destType))); + CodeAssignStatement assignment = new CodeAssignStatement( + (CodeExpression)peek(), + expr); + constructor.Statements.Add(assignment); } - CodeAssignStatement assignment = new CodeAssignStatement( - (CodeExpression)peek(), - expr); - constructor.Statements.Add(assignment); - } - - public void CreateDependencyPropertyObject(Type type, string varName) - { - CreatePropertyObject(type, varName); - } - - public void CreatePropertyObject(Type type, string varName) - { - debug(); - bool isDefaultName; - if (varName == null) { - isDefaultName = true; - varName = Char.ToLower(type.Name[0]) + type.Name.Substring(1); - // make sure something sensible happens when class - // names start with a lowercase letter - if (varName == type.Name) - varName = "_" + varName; - } else { - isDefaultName = false; + public override void EndObject() + { + debug(); + pop(); } - if (isDefaultName) { - if (!nameClashes.ContainsKey(varName)) - nameClashes[varName] = 0; - nameClashes[varName] = 1 + (int)nameClashes[varName]; - varName += (int)nameClashes[varName]; + public override void EndProperty() + { + debug(); + pop(); } - - - if (isDefaultName) { - CodeVariableDeclarationStatement declaration = - new CodeVariableDeclarationStatement(type, - varName, - new CodeObjectCreateExpression(type)); - constructor.Statements.Add(declaration); - } else { - CodeMemberField declaration = new CodeMemberField(type, varName); - declaration.InitExpression = new CodeObjectCreateExpression(type); - this.type.Members.Add(declaration); + + public override void EndEvent() + { + debug(); + pop(); } - CodeVariableReferenceExpression varRef = new CodeVariableReferenceExpression(varName); - push(type); - push(varRef); - - } - - public void EndDependencyPropertyObject(Type destType) - { - EndPropertyObject(destType); - } - public void EndPropertyObject(Type destType) - { - debug(); - CodeExpression varRef = (CodeExpression)pop(); - Type sourceType = (Type)pop(); + public override void Finish() + { + debug(); + generator.GenerateCodeFromCompileUnit(code, writer, null); + writer.Close(); + } - Debug.WriteLine("ParserToCode: " + destType + "->" + sourceType); + public override void CreateCode(string code) + { + debug(); + type.Members.Add(new CodeSnippetTypeMember(code)); + } + private void debug() + { + Debug.WriteLine("ParserToCode: " + new System.Diagnostics.StackTrace()); + } - CodeExpression expr; - if (sourceType == destType || sourceType.IsSubclassOf(destType)) - expr = varRef; - else - expr = new CodeCastExpression( - new CodeTypeReference(destType), - new CodeMethodInvokeExpression( - fetchConverter(sourceType), - "ConvertTo", - varRef, - new CodeTypeOfExpression(destType))); - CodeAssignStatement assignment = new CodeAssignStatement( - (CodeExpression)peek(), - expr); - constructor.Statements.Add(assignment); - } - - public void EndObject() - { - debug(); - pop(); - } - - public void EndProperty() - { - debug(); - pop(); - } - - public void EndEvent() - { - debug(); - pop(); - } - - public void Finish() - { - debug(); - generator.GenerateCodeFromCompileUnit(code, writer, null); - writer.Close(); - } - - public void CreateCode(string code) - { - debug(); - type.Members.Add(new CodeSnippetTypeMember(code)); - } - - private void debug() - { - Debug.WriteLine("ParserToCode: " + new System.Diagnostics.StackTrace()); - } - - private object pop() - { - object v = objects[objects.Count - 1]; - objects.RemoveAt(objects.Count - 1); - Debug.WriteLine("ParserToCode: POPPING"); - return v; - } - private void push(object v) - { - Debug.WriteLine("ParserToCode: PUSHING " + v); - objects.Add(v); - } - private object peek() - { - return peek(0); - } - private object peek(int i) - { - return objects[objects.Count - 1 - i]; + private object pop() + { + object v = objects[objects.Count - 1]; + objects.RemoveAt(objects.Count - 1); + Debug.WriteLine("ParserToCode: POPPING"); + return v; + } + private void push(object v) + { + Debug.WriteLine("ParserToCode: PUSHING " + v); + objects.Add(v); + } + private object peek() + { + return peek(0); + } + private object peek(int i) + { + return objects[objects.Count - 1 - i]; + } } } } diff --git a/mcs/class/PresentationFramework/PresentationFramework.dll.sources b/mcs/class/PresentationFramework/PresentationFramework.dll.sources index 42d829d4621..471254002a0 100644 --- a/mcs/class/PresentationFramework/PresentationFramework.dll.sources +++ b/mcs/class/PresentationFramework/PresentationFramework.dll.sources @@ -5,6 +5,7 @@ System.Windows.Serialization/Parser.cs System.Windows.Serialization/XamlNodeType.cs System.Windows.Serialization/XamlParseMode.cs System.Windows.Serialization/BamlAttributeUsage.cs +Mono.Windows.Serialization/ParserConsumerBase.cs Mono.Windows.Serialization/ParserToCode.cs Mono.Windows.Serialization/Exceptions.cs Mono.Windows.Serialization/XamlParser.cs diff --git a/mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs b/mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs index 6b5e7543059..9477cb877fc 100644 --- a/mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs +++ b/mcs/class/PresentationFramework/System.Windows.Serialization/Parser.cs @@ -1,5 +1,5 @@ // -// CodeWriter.cs +// Parser.cs - instantiate an object according to a Xaml file // // Author: // Iain McCoy (iain@mccoy.id.au) @@ -40,8 +40,6 @@ using System.Xml; namespace System.Windows.Serialization { public class Parser { - private object instance; - ArrayList objects = new ArrayList(); public static object LoadXml(Stream s) { @@ -50,249 +48,181 @@ namespace System.Windows.Serialization { // TODO: this should take a XmlReader in order to be same as MSFT public static object LoadXml(XmlTextReader reader) { - Parser r = new Parser(reader); + Consumer r = new Consumer(); + r.crunch(reader); return r.instance; } - private Parser(XmlTextReader reader) - { - XamlParser p = new XamlParser(reader); - XamlNode n; - while (true) { - n = p.GetNextNode(); - if (n == null) - break; - Debug.WriteLine("ParserToCode: INCOMING " + n.GetType()); - if (n is XamlDocumentStartNode) { - Debug.WriteLine("ParserToCode: document begins"); - // do nothing - } else if (n is XamlElementStartNode && n.Depth == 0) { - Debug.WriteLine("ParserToCode: element begins as top-level"); - CreateTopLevel(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); - } else if (n is XamlElementStartNode && ((XamlElementStartNode)n).propertyObject) { - Debug.WriteLine("ParserToCode: element begins as property value"); - CreatePropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); - } else if (n is XamlElementStartNode && ((XamlElementStartNode)n).depPropertyObject) { - Debug.WriteLine("ParserToCode: element begins as dependency property value"); - CreateDependencyPropertyObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); - - } else if (n is XamlElementStartNode) { - Debug.WriteLine("ParserToCode: element begins"); - CreateObject(((XamlElementStartNode)n).ElementType, ((XamlElementStartNode)n).name); - } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).PropInfo != null) { - Debug.WriteLine("ParserToCode: normal property begins"); - CreateProperty(((XamlPropertyNode)n).PropInfo); - } else if (n is XamlPropertyNode && ((XamlPropertyNode)n).DP != null) { - Debug.WriteLine("ParserToCode: dependency property begins"); - DependencyProperty dp = ((XamlPropertyNode)n).DP; - Type typeAttachedTo = dp.OwnerType; - string propertyName = ((XamlPropertyNode)n).PropertyName; - - CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType); - } else if (n is XamlClrEventNode && !(((XamlClrEventNode)n).EventMember is EventInfo)) { - Debug.WriteLine("ParserToCode: delegate property"); - CreatePropertyDelegate(((XamlClrEventNode)n).Value, ((PropertyInfo)((XamlClrEventNode)n).EventMember).PropertyType); - EndProperty(); - - - } else if (n is XamlClrEventNode) { - Debug.WriteLine("ParserToCode: event"); - CreateEvent((EventInfo)((XamlClrEventNode)n).EventMember); - CreateEventDelegate(((XamlClrEventNode)n).Value, ((EventInfo)((XamlClrEventNode)n).EventMember).EventHandlerType); - EndEvent(); - - } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Object){ - Debug.WriteLine("ParserToCode: text for object"); - CreateObjectText(((XamlTextNode)n).TextContent); - } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.Property){ - Debug.WriteLine("ParserToCode: text for property"); - CreatePropertyText(((XamlTextNode)n).TextContent, ((XamlTextNode)n).finalType); - EndProperty(); - } else if (n is XamlTextNode && ((XamlTextNode)n).mode == XamlParseMode.DependencyProperty){ - Debug.WriteLine("ParserToCode: text for dependency property"); - CreateDependencyPropertyText(((XamlTextNode)n).TextContent, ((XamlTextNode)n).finalType); - EndDependencyProperty(); - } else if (n is XamlPropertyComplexEndNode) { - Debug.WriteLine("ParserToCode: end complex property"); - EndProperty(); - } else if (n is XamlLiteralContentNode) { - Debug.WriteLine("ParserToCode: literal content"); - CreateCode(((XamlLiteralContentNode)n).Content); - } else if (n is XamlElementEndNode) { - Debug.WriteLine("ParserToCode: end element"); - Type ft = ((XamlElementEndNode)n).finalType; - if (((XamlElementEndNode)n).propertyObject) - EndPropertyObject(ft); - else if (((XamlElementEndNode)n).depPropertyObject) - EndDependencyPropertyObject(ft); - else - EndObject(); - } else if (n is XamlDocumentEndNode) { - Debug.WriteLine("ParserToCode: end document"); - Finish(); - } else { - throw new Exception("Unknown node " + n.GetType()); - } + private class Consumer : ParserConsumerBase { + + public object instance; + ArrayList objects = new ArrayList(); + public override void CreateTopLevel(Type parent, string className) + { + instance = Activator.CreateInstance(parent); + push(instance); } - } - - public void CreateTopLevel(Type parent, string className) - { - instance = Activator.CreateInstance(parent); - push(instance); - } + public override void CreateObject(Type type, string varName) + { + Object o = Activator.CreateInstance(type); + ((IAddChild)peek()).AddChild(o); + push(o); + } - public void CreateObject(Type type, string varName) - { - Object o = Activator.CreateInstance(type); - ((IAddChild)peek()).AddChild(o); - push(o); - } + public override void CreateProperty(PropertyInfo property) + { + push(property); + } - public void CreateProperty(PropertyInfo property) - { - push(property); - } + // top of stack is a reference to an object + // pushes a reference to the event + public override void CreateEvent(EventInfo evt) + { + push(evt); + } - // top of stack is a reference to an object - // pushes a reference to the event - public void CreateEvent(EventInfo evt) - { - push(evt); - } + public override void CreateDependencyProperty(Type attachedTo, string propertyName, Type propertyType) + { + push(attachedTo); + push(propertyName); + } - public void CreateDependencyProperty(Type attachedTo, string propertyName, Type propertyType) - { - push(attachedTo); - push(propertyName); - } + public override void EndDependencyProperty() + { + object value = pop(); + string propertyName = (string)pop(); + Type attachedTo = (Type)pop(); - public void EndDependencyProperty() - { - object value = pop(); - string propertyName = (string)pop(); - Type attachedTo = (Type)pop(); - MethodInfo setter = attachedTo.GetMethod("Set" + propertyName); - setter.Invoke(null, new object[] { peek(), value}); - } + MethodInfo setter = attachedTo.GetMethod("Set" + propertyName); + Console.WriteLine(attachedTo.GetType()+ ".Set" + propertyName + "(" + peek().GetType() + ", " + value.GetType() + ")"); + setter.Invoke(null, new object[] { peek(), value}); + } - public void CreateObjectText(string text) - { - ((IAddChild)peek()).AddText(text); - } + public override void CreateObjectText(string text) + { + ((IAddChild)peek()).AddText(text); + } - // top of stack is reference to an event - public void CreateEventDelegate(string functionName, Type eventDelegateType) - { - EventInfo e = (EventInfo)peek(); - object o = peek(1); - e.AddEventHandler(o, Delegate.CreateDelegate(o.GetType(), o, functionName)); - } - // top of stack is reference to a property - public void CreatePropertyDelegate(string functionName, Type propertyType) - { - PropertyInfo p = (PropertyInfo)peek(); - object o = peek(1); - p.SetValue(o, Delegate.CreateDelegate(o.GetType(), o, functionName), null); - } + // top of stack is reference to an event + public override void CreateEventDelegate(string functionName, Type eventDelegateType) + { + EventInfo e = (EventInfo)peek(); + object o = peek(1); + e.AddEventHandler(o, Delegate.CreateDelegate(o.GetType(), o, functionName)); + } + // top of stack is reference to a property + public override void CreatePropertyDelegate(string functionName, Type propertyType) + { + PropertyInfo p = (PropertyInfo)peek(); + object o = peek(1); + p.SetValue(o, Delegate.CreateDelegate(o.GetType(), o, functionName), null); + } - public void CreatePropertyText(string text, Type propertyType) - { - object value = text; - if (propertyType != typeof(string)) { - TypeConverter tc = TypeDescriptor.GetConverter(propertyType); - value = tc.ConvertFromString(text); + public override void CreatePropertyText(string text, Type propertyType) + { + object value = text; + if (propertyType != typeof(string)) { + TypeConverter tc = TypeDescriptor.GetConverter(propertyType); + value = tc.ConvertFromString(text); + } + storeToProperty(value); } - PropertyInfo p = (PropertyInfo)peek(); - object o = peek(1); - p.SetValue(o, value, null); - } - - public void CreatePropertyObject(Type type, string name) - { - object value = Activator.CreateInstance(type); - Debug.WriteLine("ObjectWriter CREATING PROPERTY OBJECT of type" + type); - push(value); - } - public void EndPropertyObject(Type destType) - { - object value = pop(); - Type sourceType = value.GetType(); - Debug.WriteLine("ObjectWriter: EndPropertyObject has a " + value + value.GetType() + ", needs a " + destType); - if (destType != sourceType && !sourceType.IsSubclassOf(destType)) { - TypeConverter tc = TypeDescriptor.GetConverter(destType); - value = tc.ConvertFrom(value); + + public override void CreatePropertyObject(Type type, string name) + { + object value = Activator.CreateInstance(type); + Debug.WriteLine("ObjectWriter CREATING PROPERTY OBJECT of type" + type); + push(value); + } + public override void EndPropertyObject(Type destType) + { + object value = convertPropertyObjectValue(destType); + storeToProperty(value); + } + private void storeToProperty(object value) + { + PropertyInfo p = (PropertyInfo)peek(); + object o = peek(1); + p.SetValue(o, value, null); + } + private object convertPropertyObjectValue(Type destType) + { + object value = pop(); + Type sourceType = value.GetType(); + Debug.WriteLine("ObjectWriter: EndPropertyObject has a " + value + value.GetType() + ", needs a " + destType); + if (destType != sourceType && !sourceType.IsSubclassOf(destType)) { + TypeConverter tc = TypeDescriptor.GetConverter(sourceType); + value = tc.ConvertTo(value, destType); + } + return value; } - PropertyInfo p = (PropertyInfo)peek(); - object o = peek(1); - p.SetValue(o, value, null); - } - public void CreateDependencyPropertyObject(Type type, string name) - { - throw new NotImplementedException(); - } - public void EndDependencyPropertyObject(Type finalType) - { - throw new NotImplementedException(); - } + public override void CreateDependencyPropertyObject(Type type, string name) + { + CreatePropertyObject(type, name); + } + public override void EndDependencyPropertyObject(Type finalType) + { + push(convertPropertyObjectValue(finalType)); + } - // top of stack is reference to an attached property - public void CreateDependencyPropertyText(string text, Type propertyType) - { - object value = text; - if (propertyType != typeof(string)) { - TypeConverter tc = TypeDescriptor.GetConverter(propertyType); - value = tc.ConvertFromString(text); + // top of stack is reference to an attached property + public override void CreateDependencyPropertyText(string text, Type propertyType) + { + object value = text; + if (propertyType != typeof(string)) { + TypeConverter tc = TypeDescriptor.GetConverter(propertyType); + value = tc.ConvertFromString(text); + } + push(value); + } + + public override void EndObject() + { + pop(); } - push(value); - } - - public void EndObject() - { - pop(); - } - public void EndProperty() - { - pop(); - } - - public void EndEvent() - { - pop(); - } + public override void EndProperty() + { + pop(); + } + + public override void EndEvent() + { + pop(); + } - public void Finish() - { - } + public override void Finish() + { + } - public void CreateCode(string code) - { - throw new NotImplementedException(); - } + public override void CreateCode(string code) + { + throw new NotImplementedException(); + } - private object peek() - { - return peek(0); - } - private object peek(int i) - { - return objects[objects.Count - 1 - i]; - } - private object pop() - { - object v = objects[objects.Count - 1]; - objects.RemoveAt(objects.Count - 1); - Debug.WriteLine("ObjectWriter POPPING"); - return v; - } - private void push(object v) - { - Debug.WriteLine("ObjectWriter PUSHING " + v); - objects.Add(v); + private object peek() + { + return peek(0); + } + private object peek(int i) + { + return objects[objects.Count - 1 - i]; + } + private object pop() + { + object v = objects[objects.Count - 1]; + objects.RemoveAt(objects.Count - 1); + Debug.WriteLine("ObjectWriter POPPING"); + return v; + } + private void push(object v) + { + Debug.WriteLine("ObjectWriter PUSHING " + v); + objects.Add(v); + } } } } |