diff options
Diffstat (limited to 'mcs/class/PresentationFramework')
8 files changed, 178 insertions, 20 deletions
diff --git a/mcs/class/PresentationFramework/ChangeLog b/mcs/class/PresentationFramework/ChangeLog index e10b953e243..b439335ffe7 100644 --- a/mcs/class/PresentationFramework/ChangeLog +++ b/mcs/class/PresentationFramework/ChangeLog @@ -1,3 +1,24 @@ +2005-07-14 Iain McCoy <iain@mccoy.id.au> + + * Mono.Windows.Serialization/XamlParser.cs, + Mono.Windows.Serialization/XamlWriter.cs, + Mono.Windows.Serialization/CodeWriter.cs: Initial support for + creating complex objects as values of properties + +2005-07-13 Iain McCoy <iain@mccoy.id.au> + + * Mono.Windows.Serialization/XamlParser.cs: fixed bug in the code + detecting that the file's contents must be finished, where it forbade + whitespace after the XAML code + +2005-07-11 Iain McCoy <iain@mccoy.id.au> + + * Makefile, + Test/XamlParser.cs: added a few tests + * Mono.Windows.Serialization/CodeWriter.cs, + Mono.Windows.Serialization/XamlParser.cs: fixed some bugs that the + new tests turned up + 2005-07-08 Iain McCoy <iain@mccoy.id.au> * Mono.Windows.Serialization/ObjectWriter.cs: code to build objects at diff --git a/mcs/class/PresentationFramework/Makefile b/mcs/class/PresentationFramework/Makefile index f04f16b745e..85ee60e45cf 100644 --- a/mcs/class/PresentationFramework/Makefile +++ b/mcs/class/PresentationFramework/Makefile @@ -4,6 +4,15 @@ include ../../build/rules.make LIBRARY = PresentationFramework.dll LIB_MCS_FLAGS = -r:System.Xml.dll -r:WindowsBase.dll -r:System.dll -NO_TEST = yes +TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) -r:TestVocab.dll -r:System.dll +TEST_MONO_PATH = . + +Test/XamlParser.cs: Test/TestVocab.dll + +Test/TestVocab.dll: ../../tools/xamlc/demo/TestVocab/*.cs + echo $(MONO_PATH) + (cd ../../tools/xamlc/demo; make TestVocab.dll) + cp ../../tools/xamlc/demo/TestVocab.dll Test/TestVocab.dll + cp Test/TestVocab.dll TestVocab.dll include ../../build/library.make diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs index b6939555538..204e2cc94fe 100644 --- a/mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs @@ -61,6 +61,9 @@ namespace Mono.Windows.Serialization { // instance public void CreateTopLevel(Type parent, string className) { + if (className == null) { + className = "derived" + parent.Name; + } int endNamespaceName = className.LastIndexOf("."); string clrNamespace; if (endNamespaceName < 0) @@ -231,6 +234,7 @@ namespace Mono.Windows.Serialization { "GetConverter"), new CodeTypeOfExpression(propertyType)); } + // top of stack is reference to a property public void CreatePropertyText(string text, Type propertyType) { @@ -254,6 +258,72 @@ namespace Mono.Windows.Serialization { constructor.Statements.Add(assignment); } + + public void CreatePropertyObject(Type type, string varName) + { + 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; + } + + if (!nameClashes.ContainsKey(varName)) + nameClashes[varName] = 0; + else { + 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); + + objects.Add(type); + objects.Add(varRef); + + } + + public void EndPropertyObject(Type sourceType) + { + CodeExpression varRef = (CodeExpression)objects[objects.Count - 1]; + objects.RemoveAt(objects.Count - 1); + Type destType = (Type)objects[objects.Count - 1]; + objects.RemoveAt(objects.Count - 1); + + + CodeExpression expr; + if (destType == sourceType) + expr = varRef; + else + expr = new CodeCastExpression( + new CodeTypeReference(destType), + new CodeMethodInvokeExpression( + fetchConverter(sourceType), + "ConvertTo", + varRef, + new CodeTypeOfExpression(destType))); + CodeAssignStatement assignment = new CodeAssignStatement( + (CodeExpression)objects[objects.Count - 1], + expr); + constructor.Statements.Add(assignment); + + } public void EndObject() { diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/ObjectWriter.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/ObjectWriter.cs index e4a13f8a56f..f024812150b 100644 --- a/mcs/class/PresentationFramework/Mono.Windows.Serialization/ObjectWriter.cs +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/ObjectWriter.cs @@ -103,6 +103,15 @@ namespace Mono.Windows.Serialization { p.SetValue(o, text, null); } + public void CreatePropertyObject(Type type, string name) + { + throw new NotImplementedException(); + } + public void EndPropertyObject(Type sourceType) + { + throw new NotImplementedException(); + } + // top of stack is reference to an attached property public void CreateDependencyPropertyText(string text, Type propertyType) { diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs index fb9f2a26b18..10524cfdcb2 100644 --- a/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs @@ -52,20 +52,33 @@ namespace Mono.Windows.Serialization { public CurrentType type; } + private bool begun = false; + private ParserState currentState = null; private ArrayList oldStates = new ArrayList(); - public XamlParser(string filename, XamlWriter writer) + public XamlParser(string filename, XamlWriter writer) : this( + new XmlTextReader(filename), writer) + { + } + + public XamlParser(TextReader reader, XamlWriter writer) : this( + new XmlTextReader(reader), writer) + { + } + + public XamlParser(XmlReader reader, XamlWriter writer) { - reader = new XmlTextReader(filename); + this.reader = reader; this.writer = writer; } public void Parse() { while (reader.Read()) { - if (currentState != null && - currentState.type == CurrentType.Code) + if (begun && currentState == null && reader.NodeType != XmlNodeType.Whitespace) + throw new Exception("Too far: " + reader.NodeType + ", " + reader.Name); + if (currentState != null && currentState.type == CurrentType.Code) { if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "Code" && @@ -90,7 +103,8 @@ namespace Mono.Windows.Serialization { parseText(); break; case XmlNodeType.Whitespace: - // skip whitespace + case XmlNodeType.Comment: + // skip whitespace and comments break; default: Console.Out.WriteLine("Unknown element type " + reader.NodeType); @@ -222,12 +236,22 @@ namespace Mono.Windows.Serialization { if (parent.GetInterface("System.Windows.Serialization.IAddChild") == null) {} //TODO: throw exception if (currentState == null) { + if (reader.GetAttribute("Name", XAML_NAMESPACE) != null) + throw new Exception("The XAML Name attribute can not be applied to top level elements\n"+ + "Do you mean the Class attribute?"); + begun = true; createTopLevel(parent.AssemblyQualifiedName, reader.GetAttribute("Class", XAML_NAMESPACE)); } else { string name = reader.GetAttribute("Name", XAML_NAMESPACE); if (name == null) name = reader.GetAttribute("Name", reader.NamespaceURI); - addChild(parent, name); + + if (currentState.type == CurrentType.Object) + addChild(parent, name); + else if (currentState.type == CurrentType.Property) + addPropertyChild(parent, name); + else + throw new NotImplementedException(); } if (reader.MoveToFirstAttribute()) { @@ -253,13 +277,11 @@ namespace Mono.Windows.Serialization { void createTopLevel(string parentName, string className) { Type t = Type.GetType(parentName); + + writer.CreateTopLevel(t, className); currentState = new ParserState(); currentState.type = CurrentType.Object; currentState.obj = t; - if (className == null) { - className = "derived" + t.Name; - } - writer.CreateTopLevel(t, className); } void addChild(Type type, string objectName) @@ -270,6 +292,18 @@ namespace Mono.Windows.Serialization { currentState.type = CurrentType.Object; currentState.obj = type; } + + void addPropertyChild(Type type, string objectName) + { +// writer.CreatePropertyObject(type, objectName); + writer.CreatePropertyObject(((PropertyInfo)currentState.obj).PropertyType, objectName); + + oldStates.Add(currentState); + currentState = new ParserState(); + currentState.type = CurrentType.Object; + currentState.obj = type; + } + void parseLocalPropertyAttribute() @@ -353,15 +387,22 @@ namespace Mono.Windows.Serialization { void parseEndElement() { - if (currentState.type == CurrentType.Code) + if (currentState.type == CurrentType.Code) { writer.CreateCode((string)currentState.obj); - if (currentState.type == CurrentType.Object) - writer.EndObject(); - else if (currentState.type == CurrentType.Property) + } else if (currentState.type == CurrentType.Object) { + ParserState prev = null; + if (oldStates.Count > 1) + prev = (ParserState)oldStates[oldStates.Count - 1]; + + if (prev != null && prev.type == CurrentType.Property) + writer.EndPropertyObject((Type)currentState.obj); + else + writer.EndObject(); + } else if (currentState.type == CurrentType.Property) { writer.EndProperty(); - else if (currentState.type == CurrentType.DependencyProperty) + } else if (currentState.type == CurrentType.DependencyProperty) { writer.EndDependencyProperty(); - + } pop(); } @@ -375,7 +416,6 @@ namespace Mono.Windows.Serialization { int lastIndex = oldStates.Count - 1; currentState = (ParserState)oldStates[lastIndex]; oldStates.RemoveAt(lastIndex); - } } diff --git a/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs b/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs index ba760e0b3de..5de3c224985 100644 --- a/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs +++ b/mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs @@ -40,6 +40,8 @@ namespace Mono.Windows.Serialization { void CreateProperty(PropertyInfo property); void CreatePropertyText(string text, Type propertyType); void CreatePropertyDelegate(string functionName, Type propertyType); + void CreatePropertyObject(Type destType, string name); + void EndPropertyObject(Type sourceType); void EndProperty(); diff --git a/mcs/class/PresentationFramework/PresentationFramework_test.dll.sources b/mcs/class/PresentationFramework/PresentationFramework_test.dll.sources new file mode 100644 index 00000000000..1a4ffb83b0f --- /dev/null +++ b/mcs/class/PresentationFramework/PresentationFramework_test.dll.sources @@ -0,0 +1 @@ +XamlParser.cs diff --git a/mcs/class/PresentationFramework/System.Windows.Serialization/Mapper.cs b/mcs/class/PresentationFramework/System.Windows.Serialization/Mapper.cs index 3594d898878..4f1683a52a5 100644 --- a/mcs/class/PresentationFramework/System.Windows.Serialization/Mapper.cs +++ b/mcs/class/PresentationFramework/System.Windows.Serialization/Mapper.cs @@ -133,9 +133,15 @@ namespace System.Windows.Serialization { Assembly getAssembly(string name) { - if (assemblyPath[name] != null) + if (assemblyPath.ContainsKey(name)) name = (string)assemblyPath[name]; - return Assembly.Load(name); + Assembly result = Assembly.LoadFrom(name); + if (result == null) + result = Assembly.Load(name); + if (result == null) + throw new Exception("Could not find assembly with name " + name); + else + return result; } public void SetAssemblyPath(string assemblyName, string assemblyPath) |