++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
"GetConverter"),
new CodeTypeOfExpression(propertyType));
}
++
// top of stack is reference to a property
public void CreatePropertyText(string text, Type propertyType)
{
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()
{
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)
{
public void Parse()
{
while (reader.Read()) {
- if (begun && currentState == null)
- 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" &&
parseText();
break;
case XmlNodeType.Whitespace:
-- // skip whitespace
++ case XmlNodeType.Comment:
++ // skip whitespace and comments
break;
default:
Console.Out.WriteLine("Unknown element type " + reader.NodeType);
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()) {
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)
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()
void parseEndElement()
{
-- if (currentState.type == CurrentType.Code)
++ if (currentState.type == CurrentType.Code) {
writer.CreateCode((string)currentState.obj);
- else if (currentState.type == CurrentType.Object)
- 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();
}
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();
-2005-07-06 Iain McCoy <iain@mccoy.id.au>
++2005-07-14 Iain McCoy <iain@mccoy.id.au>
++
++ * demo/test.xaml: added first test of complex objects as property values
++
++
++2005-07-13 Iain McCoy <iain@mccoy.id.au>
++
++ * demo/TestVocab/ConsoleReader.cs,
++ demo/TestVocab/ConsoleVars.cs: more functionality that will provide
++ uses for more complicated xaml code.
++ * xamlc.cs: much more useful error reporting.
++
++2005-07-08 Iain McCoy <iain@mccoy.id.au>
++
++ * demo/TestVocab/ConsoleWriter.cs,
++ demo/TestVocab/ConsoleValue.cs,
++ demo/Makefile: Added ConsoleValue class to allow testing of more
++ complicated property scenarios
++ * demo/TestVocab/ConsoleVars.cs,
++ demo/TestVocab/ConsoleReader.cs: classes to put in more complicated
++ test
++
+2005-07-08 Iain McCoy <iain@mccoy.id.au>
* demo/runtimetest.xaml
demo/runtimetest.cs,
thisdir = tools/xaml/demo
include ../../../build/rules.make
--SOURCES=TestVocab/ConsoleApp.cs TestVocab/ConsoleWriter.cs TestVocab/IConsoleAction.cs
++SOURCES=TestVocab/ConsoleApp.cs TestVocab/ConsoleWriter.cs TestVocab/ConsoleReader.cs TestVocab/IConsoleAction.cs TestVocab/ConsoleValue.cs TestVocab/ConsoleVars.cs
run:
make clean
public void AddText(string Text)
{
-- actions.Add(new ConsoleWriter(Text));
++ actions.Add(new ConsoleWriter(
++ new ConsoleValueString(Text)));
}
public void AddChild(object Value)
--- /dev/null
--- /dev/null
++using System.Windows;
++
++namespace Xaml.TestVocab.Console {
++ public class ConsoleReader : DependencyObject, IConsoleAction {
++ private string variable;
++ private ConsoleWriter prompt;
++
++ public string Variable {
++ get { return variable; }
++ set { variable = value; }
++ }
++
++ public ConsoleWriter Prompt {
++ get { return prompt; }
++ set { prompt = value; }
++ }
++
++ public void Run() {
++ prompt.Run();
++ string s = System.Console.ReadLine();
++ ConsoleVars.Set(variable, s);
++ }
++ }
++}
--- /dev/null
--- /dev/null
++using System;
++using System.Globalization;
++using System.ComponentModel;
++
++
++namespace Xaml.TestVocab.Console {
++
++ [TypeConverter(typeof(ConsoleValueConverter))]
++ public abstract class ConsoleValue {
++ public abstract string Value { get; }
++ }
++
++ public class ConsoleValueConverter : TypeConverter {
++ public override bool CanConvertFrom(ITypeDescriptorContext context, Type t)
++ {
++ return (t == typeof(ConsoleValue));
++ }
++ public override bool CanConvertTo(ITypeDescriptorContext context, Type t)
++ {
++ return (t == typeof(string));
++ }
++ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object o)
++ {
++ if (o is string)
++ return new ConsoleValueString((string)o);
++ else
++ throw new NotSupportedException();
++ }
++ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, Object o, Type destinationType)
++ {
++ if (destinationType != typeof(string))
++ throw new NotSupportedException();
++ if (o is ConsoleValue)
++ return ((ConsoleValue)o).Value;
++ else
++ throw new NotSupportedException();
++ }
++ }
++
++
++
++ public class ConsoleValueString : ConsoleValue {
++ string val;
++ public ConsoleValueString(string val)
++ {
++ this.val = val;
++ }
++
++ public override string Value {
++ get { return val; }
++ }
++ }
++
++ public class ConsoleValueVar : ConsoleValue {
++ string var;
++ public ConsoleValueVar()
++ {
++ }
++
++ public ConsoleValueVar(string var)
++ {
++ this.var = var;
++ }
++
++ public override string Value {
++ get { return ConsoleVars.Get(var); }
++ }
++
++ public string Variable {
++ get { return var; }
++ set { var = value; }
++ }
++ }
++
++}
--- /dev/null
--- /dev/null
++using System.Collections;
++
++namespace Xaml.TestVocab.Console {
++ public class ConsoleVars {
++ private static Hashtable storage = new Hashtable();
++ public static void Set(string name, string o) {
++ storage[name] = o;
++ }
++ public static string Get(string name) {
++ return (string)storage[name];
++ }
++ }
++}
text = "";
}
-- public ConsoleWriter(string text)
++ public ConsoleWriter(ConsoleValue text)
{
-- this.text = text;
++ this.text = text.Value;
}
public string Text {
public void AddChild(Object o)
{
-- throw new NotImplementedException();
++ this.text += ((ConsoleValue)o).Value;
}
--<?Mapping ClrNamespace="Xaml.TestVocab.Console" Assembly="TestVocab" XmlNamespace="console" ?>
++<?Mapping ClrNamespace="Xaml.TestVocab.Console" Assembly="TestVocab.dll" XmlNamespace="console" ?>
<ConsoleApp xmlns="console"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
<ConsoleWriter>IT BEGINS!</ConsoleWriter>
<ConsoleWriter x:Name="_greeter" Text="Hello World" />
<ConsoleWriter Text="I'm surrounded!" Filter="stringFilter" />
++ <ConsoleReader Variable="thingo">
++ <ConsoleReader.Prompt>
++ <ConsoleWriter>What should I say?</ConsoleWriter>
++ </ConsoleReader.Prompt>
++ </ConsoleReader>
++<!--
++ <ConsoleWriter>
++ <ConsoleWriter.Text>
++ <ConsoleValueVar Variable="thingo" />
++ </ConsoleWriter.Text>
++ </ConsoleWriter>
++-->
<ConsoleWriter>
<ConsoleApp.Repetitions>3</ConsoleApp.Repetitions>
<ConsoleWriter.Text>Goodbye.</ConsoleWriter.Text>
using System;
using System.IO;
++using System.Xml;
using System.CodeDom;
using System.CodeDom.Compiler;
using Mono.GetOptions;
options.OutputFile = input + ".out";
}
ICodeGenerator generator = (new Microsoft.CSharp.CSharpCodeProvider()).CreateGenerator();
++ XmlTextReader xr = new XmlTextReader(input);
TextWriter tw = new StreamWriter(options.OutputFile);
CodeWriter cw = new CodeWriter(generator, tw, options.Partial);
-- XamlParser r = new XamlParser(input, cw);
-- r.Parse();
++ XamlParser r = new XamlParser(xr, cw);
++ try {
++ r.Parse();
++ }
++ catch (Exception ex) {
++ Console.WriteLine("Line " + xr.LineNumber + ", Column " + xr.LinePosition);
++ throw ex;
++ }
}
public static void Main(string[] args) {