2005-07-14 Iain McCoy <iain@mccoy.id.au>
authorIain McCoy <iainmc@mono-cvs.ximian.com>
Thu, 14 Jul 2005 02:35:58 +0000 (02:35 -0000)
committerIain McCoy <iainmc@mono-cvs.ximian.com>
Thu, 14 Jul 2005 02:35:58 +0000 (02:35 -0000)
* demo/test.xaml: added first test of complex objects as property values
* 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.
* 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
* 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
* 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

svn path=/trunk/mcs/; revision=47291

14 files changed:
1  2 
mcs/class/PresentationFramework/ChangeLog
mcs/class/PresentationFramework/Mono.Windows.Serialization/CodeWriter.cs
mcs/class/PresentationFramework/Mono.Windows.Serialization/ObjectWriter.cs
mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlParser.cs
mcs/class/PresentationFramework/Mono.Windows.Serialization/XamlWriter.cs
mcs/tools/xamlc/ChangeLog
mcs/tools/xamlc/demo/Makefile
mcs/tools/xamlc/demo/TestVocab/ConsoleApp.cs
mcs/tools/xamlc/demo/TestVocab/ConsoleReader.cs
mcs/tools/xamlc/demo/TestVocab/ConsoleValue.cs
mcs/tools/xamlc/demo/TestVocab/ConsoleVars.cs
mcs/tools/xamlc/demo/TestVocab/ConsoleWriter.cs
mcs/tools/xamlc/demo/test.xaml
mcs/tools/xamlc/xamlc.cs

index f456ff7d70668349a3c577afbc4ed1a5fda0fc9e,e10b953e243d9ab367c239663fad3b91da44b553..b439335ffe715f9ec04502fb7d24546c2ce6b3f9
@@@ -1,11 -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
index 5a39087f1924d412daa865f0192227ed6279c026,b6939555538338b87ca438691782257203743f39..204e2cc94fe5f2b3251e401465f2581d0b1d4927
@@@ -234,6 -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)
                {
                        
                        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()
                {
index e4a13f8a56f36f0276a748d35703cdf0bdd470b7,e4a13f8a56f36f0276a748d35703cdf0bdd470b7..f024812150bf8be0950f48a6b548f88498ca2aa6
@@@ -103,6 -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)
                {
index 39bdcf453496ba8b096bf2665e6942622f3986dc,fb9f2a26b1898f838cede4fd5c84e94fea36d849..10524cfdcb219b0939c25d874c16b4e74f9db1ae
@@@ -76,9 -64,8 +76,9 @@@ namespace Mono.Windows.Serialization 
                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();
                }
  
index ba760e0b3de3be1df4e985ba9fb4ba385b372582,ba760e0b3de3be1df4e985ba9fb4ba385b372582..5de3c224985d10be258a22ccc953c42c6f025947
@@@ -40,6 -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();
        
  
index 365f5a6da9272f7becf287c87d1c2c9b7929f5dd,05f44e677dd4bd3bf0b432006e3bc4111e136a08..c339007d811faa31608a2bfdaf77e857f59c27dd
@@@ -1,4 -1,4 +1,26 @@@
 -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,
index 2d0591ced3d2ebc6b60c076c91520223b7b3e436,2d0591ced3d2ebc6b60c076c91520223b7b3e436..89ac4bd73292f2e9dd2b0a296c8191d63846cce9
@@@ -1,7 -1,7 +1,7 @@@
  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
index 168b7d85c3e69a6bd0b44a1a96cc0cbdb85f6091,168b7d85c3e69a6bd0b44a1a96cc0cbdb85f6091..62412218c2c53b624f2452c3f30c73a77021c9f1
@@@ -12,7 -12,7 +12,8 @@@ namespace Xaml.TestVocab.Console 
                
                public void AddText(string Text)
                {
--                      actions.Add(new ConsoleWriter(Text));
++                      actions.Add(new ConsoleWriter(
++                                              new ConsoleValueString(Text)));
                }
  
                public void AddChild(object Value)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..89da77e616d7ab6dbfb67cd0389e2db7505faa8d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,24 @@@
++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);
++              }
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..18bedb7a0293017d0b0bdd6a404f1ba3d06c10ae
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,75 @@@
++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; }
++              }
++      }
++
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..26b04aca41a984828f65b6fdc3465b65c568b671
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,13 @@@
++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];
++              }
++      }
++}
index ad636e08ad34b49d0df5882ae8324deb340aebc8,ad636e08ad34b49d0df5882ae8324deb340aebc8..9d2e9d63dcf273ec98040d46601b65e128dd5afb
@@@ -14,9 -14,9 +14,9 @@@ namespace Xaml.TestVocab.Console 
                        text = "";
                }
                
--              public ConsoleWriter(string text)
++              public ConsoleWriter(ConsoleValue text)
                {
--                      this.text = text;
++                      this.text = text.Value;
                }
  
                public string Text {
@@@ -35,7 -35,7 +35,7 @@@
  
                public void AddChild(Object o)
                {
--                      throw new NotImplementedException();
++                      this.text += ((ConsoleValue)o).Value;
                }
  
                
index 27119fc94a85264920e95eef0c9b7fa0d828bb5b,27119fc94a85264920e95eef0c9b7fa0d828bb5b..ddefc829a06e6bbde6c678ca7d304abf302542af
@@@ -1,4 -1,4 +1,4 @@@
--<?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" 
@@@ -7,6 -7,6 +7,18 @@@
        <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>
index 2759f32c6426a5d5ab325f2324c4f23f481b1bf5,2759f32c6426a5d5ab325f2324c4f23f481b1bf5..5983ddf47ebbe7ff9502b5e6bc90435d6d7b8e83
@@@ -28,6 -28,6 +28,7 @@@
  
  using System;
  using System.IO;
++using System.Xml;
  using System.CodeDom;
  using System.CodeDom.Compiler;
  using Mono.GetOptions;
@@@ -55,10 -55,10 +56,17 @@@ class Driver 
                        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) {