From 8dcac53903c37878d54d59066eb7f80da1d62bc7 Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Tue, 29 Sep 2015 10:07:13 +0200 Subject: [PATCH] generate c# with codedom for GOML MonoDevelop.GOLib addin --- GOLib.csproj | 8 +- GOLib.sln | 1 + GOMLViewer/GOMLViewer.csproj | 60 +++ GOMLViewer/Properties/AddinInfo.cs | 15 + GOMLViewer/Properties/AssemblyInfo.cs | 47 ++ GOMLViewer/Properties/Manifest.addin.xml | 17 + GOMLViewer/packages.config | 4 + GOMLViewer/src/DisplayBinding.cs | 79 +++ GOMLViewer/src/GOLibGtkHost.cs | 550 ++++++++++++++++++++ GOMLViewer/src/GOLibNodeExtension.cs | 83 +++ GOMLViewer/src/GOLibView.cs | 95 ++++ MonoDevelop.GOLib/MonoDevelop.GOLib.csproj | 44 +- MonoDevelop.GOLib/src/DisplayBinding.cs | 6 +- MonoDevelop.GOLib/src/GOLibGtkHost.cs | 153 ++++-- MonoDevelop.GOLib/src/GOLibNodeExtension.cs | 15 + MonoDevelop.GOLib/src/GOLibView.cs | 3 + Tests/GOLIBTests.cs | 21 +- Tests/Interfaces/test0.goml | 11 +- Tests/Interfaces/test2.goml | 2 +- Tests/Interfaces/testBorder.goml.cs | 31 ++ Tests/Interfaces/testContainer.goml | 2 +- Tests/Interfaces/testGrid.goml | 2 +- Tests/Interfaces/testGroupBox.goml | 5 +- Tests/Interfaces/test_stack.goml | 19 +- Tests/Tests.csproj | 19 +- src/CompilerServices/CompilerServices.cs | 142 +++++ src/GraphicObjects/GraphicObject.cs | 119 ++--- src/GraphicObjects/Group.cs | 2 +- src/GraphicObjects/PrivateContainer.cs | 2 +- src/GraphicObjects/Scroller.cs | 2 +- src/Interface.cs | 380 ++++++++++++-- 31 files changed, 1722 insertions(+), 217 deletions(-) create mode 100644 GOMLViewer/GOMLViewer.csproj create mode 100644 GOMLViewer/Properties/AddinInfo.cs create mode 100644 GOMLViewer/Properties/AssemblyInfo.cs create mode 100644 GOMLViewer/Properties/Manifest.addin.xml create mode 100644 GOMLViewer/packages.config create mode 100644 GOMLViewer/src/DisplayBinding.cs create mode 100644 GOMLViewer/src/GOLibGtkHost.cs create mode 100644 GOMLViewer/src/GOLibNodeExtension.cs create mode 100644 GOMLViewer/src/GOLibView.cs create mode 100644 Tests/Interfaces/testBorder.goml.cs diff --git a/GOLib.csproj b/GOLib.csproj index 97ec362e..989740d6 100644 --- a/GOLib.csproj +++ b/GOLib.csproj @@ -134,17 +134,17 @@ - - rsvg2-sharp-2.0 - glib-sharp-3.0 - ..\opentk\Binaries\OpenTK\Release\OpenTK.dll + + + rsvg2-sharp-2.0 + - - - + + - + diff --git a/Tests/Interfaces/test2.goml b/Tests/Interfaces/test2.goml index 05cecda3..cddc3457 100755 --- a/Tests/Interfaces/test2.goml +++ b/Tests/Interfaces/test2.goml @@ -3,7 +3,7 @@ Margin="10" Focusable="True" Fit="True" Background="Green">--> - \ No newline at end of file diff --git a/Tests/Interfaces/testBorder.goml.cs b/Tests/Interfaces/testBorder.goml.cs new file mode 100644 index 00000000..f473a4fd --- /dev/null +++ b/Tests/Interfaces/testBorder.goml.cs @@ -0,0 +1,31 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 4.0.30319.17020 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +using System; + + +namespace go { + + public partial class testBorder : Border { + public testBorder() { + this.BorderWidth = 5; + this.Width = 200; + this.Height = 200; + this.CornerRadius = 20; + this.Margin = 0; + this.Background = go.Color.Mantis; + this.SetChild(new go.GraphicObject()); + this.Child.CornerRadius = 0; + this.Child.Background = go.Color.CornflowerBlue; + this.Child.Height = 100; + this.Child.Width = 100; + } + } +} diff --git a/Tests/Interfaces/testContainer.goml b/Tests/Interfaces/testContainer.goml index 792c87c6..d93820ed 100755 --- a/Tests/Interfaces/testContainer.goml +++ b/Tests/Interfaces/testContainer.goml @@ -1,5 +1,5 @@  - + diff --git a/Tests/Interfaces/testGrid.goml b/Tests/Interfaces/testGrid.goml index 24784922..a2e052e2 100755 --- a/Tests/Interfaces/testGrid.goml +++ b/Tests/Interfaces/testGrid.goml @@ -1,6 +1,6 @@  - + diff --git a/Tests/Interfaces/testGroupBox.goml b/Tests/Interfaces/testGroupBox.goml index fd328be4..b00295a0 100755 --- a/Tests/Interfaces/testGroupBox.goml +++ b/Tests/Interfaces/testGroupBox.goml @@ -1,7 +1,4 @@  - - - - + diff --git a/Tests/Interfaces/test_stack.goml b/Tests/Interfaces/test_stack.goml index 2991a92e..2a5d0367 100755 --- a/Tests/Interfaces/test_stack.goml +++ b/Tests/Interfaces/test_stack.goml @@ -2,19 +2,24 @@ - - diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index ca65a6b0..a53e9525 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -42,6 +42,9 @@ ..\..\opentk\Binaries\OpenTK\Release\OpenTK.dll + + ..\bin\Release\golib.dll + @@ -51,6 +54,16 @@ + + + Interfaces\testContainer.goml.cs + + + Interfaces\test_stack.goml.cs + + + Interfaces\test4.goml.cs + @@ -173,12 +186,6 @@ - - - {C2980F9B-4798-4C05-99E2-E174810F7C7B} - GOLib - - diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index 17d36f13..22585f95 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -10,9 +10,151 @@ using System.Runtime.CompilerServices; namespace go { + public enum BindingType + { + Handler, + DynamicHandler, + PropertyBinding + } + public class Binding{ + public BindingType BindingType; + public string MemberName; + public string BindingExpression; + } + + public static class CompilerServices2 + { + static int dynHandleCpt = 0; + /// + /// Compile events expression in GOML attributes + /// + /// Event binding details + public static void ResolveBinding(DynAttribute es) + { + Type srcType = es.Source.GetType (); + + #region Retrieve EventHandler parameter type + EventInfo ei = srcType.GetEvent (es.MemberName); + MethodInfo invoke = ei.EventHandlerType.GetMethod ("Invoke"); + ParameterInfo[] pars = invoke.GetParameters (); + + Type handlerArgsType = pars [1].ParameterType; + #endregion + + Type[] args = {typeof(object), handlerArgsType}; + DynamicMethod dm = new DynamicMethod("dynHandle_" + dynHandleCpt, + typeof(void), + args, + srcType.Module); + + es.Source.DynamicMethodIds.Add (dynHandleCpt); + + dynHandleCpt++; + + #region IL generation + ILGenerator il = dm.GetILGenerator(256); + + string src = es.Value.Trim(); + + if (! (src.StartsWith("{") || src.EndsWith ("}"))) + throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", es.MemberName, es.Value)); + + src = src.Substring (1, src.Length - 2); + string[] srcLines = src.Split (new char[] { ';' }); + + foreach (string srcLine in srcLines) { + string statement = srcLine.Trim (); + + string[] operandes = statement.Split (new char[] { '=' }); + if (operandes.Length < 2) //not an affectation + { + continue; + } + string lop = operandes [0].Trim (); + string rop = operandes [operandes.Length-1].Trim (); + + #region LEFT OPERANDES + GraphicObject lopObj = es.Source; //default left operand base object is + //the first arg (object sender) of the event handler + + string[] lopParts = lop.Split (new char[] { '.' }); + if (lopParts.Length == 2) {//should search also for member of es.Source + lopObj = es.Source.FindByName (lopParts [0]); + if (lopObj==null) + throw new Exception (string.Format("GOML:Unknown name: {0}", lopParts[0])); + //TODO: should create private member holding ref of lopObj, and emit + //a call to FindByName(lopObjName) during #ctor or in a onLoad func or evt handler + throw new Exception (string.Format("GOML:obj tree ref not yet implemented", lopParts[0])); + }else + il.Emit(OpCodes.Ldarg_0); //load sender ref onto the stack + + int i = lopParts.Length -1; + + MemberInfo lopMbi = lopObj.GetType().GetMember (lopParts[i])[0]; + OpCode lopSetOC; + dynamic lopSetMbi; + Type lopT = null; + switch (lopMbi.MemberType) { + case MemberTypes.Property: + PropertyInfo lopPi = srcType.GetProperty (lopParts[i]); + MethodInfo dstMi = lopPi.GetSetMethod (); + lopT = lopPi.PropertyType; + lopSetMbi = dstMi; + lopSetOC = OpCodes.Callvirt; + break; + case MemberTypes.Field: + FieldInfo dstFi = srcType.GetField(lopParts[i]); + lopT = dstFi.FieldType; + lopSetMbi = dstFi; + lopSetOC = OpCodes.Stfld; + break; + default: + throw new Exception (string.Format("GOML:member type not handle: {0}", lopParts[i])); + } + #endregion + + #region RIGHT OPERANDES + if (rop.StartsWith("\'")){ + if (!rop.EndsWith("\'")) + throw new Exception (string.Format + ("GOML:malformed string constant in handler: {0}", rop)); + string strcst = rop.Substring (1, rop.Length - 2); + + il.Emit(OpCodes.Ldstr,strcst); + + }else{ + //search for a static field in left operand type named 'rop name' + FieldInfo ropFi = lopT.GetField (rop, BindingFlags.Static|BindingFlags.Public); + if (ropFi != null) + { + il.Emit (OpCodes.Ldsfld, ropFi); + }else{ + //search if parsing methods are present + MethodInfo lopTryParseMi = lopT.GetMethod("TryParse"); + + } + } + + #endregion + + //emit left operand assignment + il.Emit(lopSetOC, lopSetMbi); + } + + il.Emit(OpCodes.Ret); + + #endregion + + Delegate del = dm.CreateDelegate(ei.EventHandlerType); + MethodInfo addHandler = ei.GetAddMethod (); + addHandler.Invoke(es.Source, new object[] {del}); + } + + } public static class CompilerServices { static int dynHandleCpt = 0; + /// /// Compile events expression in GOML attributes /// diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index 443fa653..63d10122 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -18,7 +18,7 @@ using System.IO; using System.Xml; namespace go -{ +{ public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange { internal List DynamicMethodIds = new List (); @@ -47,19 +47,19 @@ namespace go #region private fields ILayoutable _parent; - string _name; - Color _background; - Color _foreground; - Font _font; - double _cornerRadius; - int _margin; + string _name = "unamed"; + Color _background = Color.Transparent; + Color _foreground = Color.White; + Font _font = "droid, 10"; + double _cornerRadius = 0; + int _margin = 0; bool _focusable = false; bool _hasFocus = false; protected bool _isVisible = true; - VerticalAlignment _verticalAlignment; - HorizontalAlignment _horizontalAlignment; - Size _maximumSize; - Size _minimumSize; + VerticalAlignment _verticalAlignment = VerticalAlignment.Center; + HorizontalAlignment _horizontalAlignment = HorizontalAlignment.Center; + Size _maximumSize = "0;0"; + Size _minimumSize = "0;0"; Picture _backgroundImage; string _backgroundImagePath; @@ -709,7 +709,7 @@ namespace go { return Visible ? ScreenCoordinates(Slot).ContainsOrIsEqual (m) : false; } - internal virtual void checkHoverWidget(MouseMoveEventArgs e) + public virtual void checkHoverWidget(MouseMoveEventArgs e) { IGOLibHost glh = TopContainer; if (glh.hoverWidget != this) { @@ -788,6 +788,10 @@ namespace go while (reader.MoveToNextAttribute ()) { string attName = reader.Name; string attValue = reader.Value; + + if (string.IsNullOrEmpty (attValue)) + continue; + MemberInfo mi = thisType.GetMember (attName).FirstOrDefault(); if (mi == null) { Debug.WriteLine (Interface.CurrentGOMLPath + "=>GOML: Unknown attribute in " + thisType.ToString() + " : " + attName); @@ -812,69 +816,68 @@ namespace go bool isAttribute = false; object defaultValue = null; - foreach (object o in pi.GetCustomAttributes ()) { - XmlAttributeAttribute xaa = o as XmlAttributeAttribute; + foreach (object attrib in pi.GetCustomAttributes ()) { + XmlAttributeAttribute xaa = attrib as XmlAttributeAttribute; if (xaa != null) { isAttribute = true; if (!string.IsNullOrEmpty (xaa.AttributeName)) attName = xaa.AttributeName; continue; } - if (o is XmlIgnoreAttribute) + if (attrib is XmlIgnoreAttribute) break; - DefaultValueAttribute dv = o as DefaultValueAttribute; + DefaultValueAttribute dv = attrib as DefaultValueAttribute; if (dv != null) defaultValue = dv.Value; } if (!isAttribute) continue; - - if (string.IsNullOrEmpty (attValue)) { - //avoid system types automaticaly converted by parser - if (defaultValue != null && !pi.PropertyType.Namespace.StartsWith("System")) { - if (pi.PropertyType != defaultValue.GetType()) { - MethodInfo miParse = pi.PropertyType.GetMethod ("Parse", BindingFlags.Static | BindingFlags.Public); - if (miParse != null) { - pi.SetValue (this, miParse.Invoke (null, new object[]{ defaultValue }), null); - continue; - } - } - } - pi.SetValue (this, defaultValue, null); - } else { - - if (attValue.StartsWith("{")) { - if (Interface.DontResoveGOML) - continue; - //binding - if (!attValue.EndsWith("}")) - throw new Exception (string.Format("GOML:Malformed binding: {0}", attValue)); - - string strBinding = attValue.Substring (1, attValue.Length - 2); - Interface.GOMLResolver.Add (new DynAttribute () { - Source = this, - MemberName = attName, - Value = strBinding - }); +// { +// //avoid system types automaticaly converted by parser +// if (defaultValue != null && !pi.PropertyType.Namespace.StartsWith("System")) { +// if (pi.PropertyType != defaultValue.GetType()) { +// MethodInfo miParse = pi.PropertyType.GetMethod ("Parse", BindingFlags.Static | BindingFlags.Public); +// if (miParse != null) { +// pi.SetValue (this, miParse.Invoke (null, new object[]{ defaultValue }), null); +// continue; +// } +// } +// } +// pi.SetValue (this, defaultValue, null); +// } else { + + if (attValue.StartsWith("{")) { + if (Interface.DontResoveGOML) continue; - } + //binding + if (!attValue.EndsWith("}")) + throw new Exception (string.Format("GOML:Malformed binding: {0}", attValue)); + + string strBinding = attValue.Substring (1, attValue.Length - 2); + Interface.GOMLResolver.Add (new DynAttribute () { + Source = this, + MemberName = attName, + Value = strBinding + }); + continue; + } - if (pi.PropertyType == typeof(string)) { - pi.SetValue (this, attValue, null); - continue; - } + if (pi.PropertyType == typeof(string)) { + pi.SetValue (this, attValue, null); + continue; + } - object o = null; + object o = null; - if (pi.PropertyType.IsEnum) { - o = Enum.Parse (pi.PropertyType, attValue); - } else { - MethodInfo me = pi.PropertyType.GetMethod ("Parse", new Type[] { typeof(string) }); - o = me.Invoke (null, new string[] { attValue }); - } + if (pi.PropertyType.IsEnum) { + pi.SetValue (this, Enum.Parse (pi.PropertyType, attValue), null); + } else { + MethodInfo me = pi.PropertyType.GetMethod ("Parse", new Type[] { typeof(string) }); + pi.SetValue (this, me.Invoke (null, new string[] { attValue }), null); + } + + - pi.SetValue (this, o, null); - } } } reader.MoveToElement(); diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index 179c4116..f711bb88 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -222,7 +222,7 @@ namespace go #region Mouse handling - internal override void checkHoverWidget (OpenTK.Input.MouseMoveEventArgs e) + public override void checkHoverWidget (OpenTK.Input.MouseMoveEventArgs e) { if (TopContainer.hoverWidget != this) { TopContainer.hoverWidget = this; diff --git a/src/GraphicObjects/PrivateContainer.cs b/src/GraphicObjects/PrivateContainer.cs index 010fca71..3d29177d 100644 --- a/src/GraphicObjects/PrivateContainer.cs +++ b/src/GraphicObjects/PrivateContainer.cs @@ -138,7 +138,7 @@ namespace go #endregion #region Mouse handling - internal override void checkHoverWidget (MouseMoveEventArgs e) + public override void checkHoverWidget (MouseMoveEventArgs e) { base.checkHoverWidget (e); if (child != null) diff --git a/src/GraphicObjects/Scroller.cs b/src/GraphicObjects/Scroller.cs index 1ee4e1bb..b0fdc120 100644 --- a/src/GraphicObjects/Scroller.cs +++ b/src/GraphicObjects/Scroller.cs @@ -128,7 +128,7 @@ namespace go { return Visible ? base.ScreenCoordinates(Slot).ContainsOrIsEqual (m) : false; } - internal override void checkHoverWidget (MouseMoveEventArgs e) + public override void checkHoverWidget (MouseMoveEventArgs e) { Point m = e.Position - new Point ((int)ScrollX, (int)ScrollY); base.checkHoverWidget (new MouseMoveEventArgs(m.X,m.Y,e.XDelta,e.YDelta)); diff --git a/src/Interface.cs b/src/Interface.cs index f988a17a..7712b577 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -26,6 +26,10 @@ using System.Diagnostics; using System.Collections.Generic; using System.Xml; using System.Linq; +using System.Reflection.Emit; +using System.CodeDom; +using Microsoft.CSharp; +using System.CodeDom.Compiler; namespace go { @@ -43,25 +47,27 @@ namespace go /// /// Graphic objects References use in dynamic delegates for binding /// - public static List References = new List(); - public static Queue FreeRefIndices = new Queue(); - public static void Unreference(Object o) + public static List References = new List (); + public static Queue FreeRefIndices = new Queue (); + + public static void Unreference (Object o) { int idxt = Interface.References.IndexOf (o); if (idxt < 0) return; - References[idxt] = null; + References [idxt] = null; FreeRefIndices.Enqueue (idxt); } + /// register target object reference in an array for binding CIL - public static int Reference(object o) + public static int Reference (object o) { - int dstIdx = Interface.References.IndexOf(o); + int dstIdx = Interface.References.IndexOf (o); if (dstIdx < 0) { if (FreeRefIndices.Count == 0) { - dstIdx = Interface.References.Count(); + dstIdx = Interface.References.Count (); Interface.References.Add (o); } else { dstIdx = FreeRefIndices.Dequeue (); @@ -70,40 +76,40 @@ namespace go } return dstIdx; } - public static LayoutingQueue LayoutingQueue = new LayoutingQueue(); + + public static LayoutingQueue LayoutingQueue = new LayoutingQueue (); #region Load/Save - internal static Stack> GOMLResolutionStack = new Stack>(); - internal static List GOMLResolver - { - get { return GOMLResolutionStack.Peek ();} + internal static Stack> GOMLResolutionStack = new Stack> (); + + internal static List GOMLResolver { + get { return GOMLResolutionStack.Peek (); } } //internal static List Bindings; - public static void Save(string file, T graphicObject) + public static void Save (string file, T graphicObject) { - XmlSerializerNamespaces xn = new XmlSerializerNamespaces(); - xn.Add("", ""); - XmlSerializer xs = new XmlSerializer(typeof(T)); - - xs = new XmlSerializer(typeof(T)); - using (Stream s = new FileStream(file, FileMode.Create)) - { - xs.Serialize(s, graphicObject, xn); + XmlSerializerNamespaces xn = new XmlSerializerNamespaces (); + xn.Add ("", ""); + XmlSerializer xs = new XmlSerializer (typeof(T)); + + xs = new XmlSerializer (typeof(T)); + using (Stream s = new FileStream (file, FileMode.Create)) { + xs.Serialize (s, graphicObject, xn); } } - public static Stream GetStreamFromPath(string path) + public static Stream GetStreamFromPath (string path) { Stream stream = null; if (path.StartsWith ("#")) { string resId = path.Substring (1); - stream = System.Reflection.Assembly.GetEntryAssembly().GetManifestResourceStream(resId); + stream = System.Reflection.Assembly.GetEntryAssembly ().GetManifestResourceStream (resId); if (stream == null)//try to find ressource in golib assembly - stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resId); + stream = System.Reflection.Assembly.GetExecutingAssembly ().GetManifestResourceStream (resId); if (stream == null) throw new Exception ("Resource not found: " + path); } else { @@ -113,38 +119,312 @@ namespace go } return stream; } + /// /// Pre-read first node to set GraphicObject class for loading /// and reset stream position to 0 /// - public static Type GetTopContainerOfGOMLStream(Stream stream){ + public static Type GetTopContainerOfGOMLStream (Stream stream) + { string root = "Object"; - stream.Seek(0,SeekOrigin.Begin); + string ClassName = ""; + stream.Seek (0, SeekOrigin.Begin); using (XmlReader reader = XmlReader.Create (stream)) { - while (reader.Read()) { + while (reader.Read ()) { // first element is the root element if (reader.NodeType == XmlNodeType.Element) { root = reader.Name; + ClassName = reader.GetAttribute ("Class"); + if (!string.IsNullOrEmpty (ClassName)) + break; + if (CurrentGOMLPath.StartsWith ("#")) + ClassName = Path.GetFileNameWithoutExtension (CurrentGOMLPath.Substring (1)); + else + ClassName = Path.GetFileNameWithoutExtension (CurrentGOMLPath); break; } } } - Type t = Type.GetType("go." + root); - //var go = Activator.CreateInstance(t); - stream.Seek(0,SeekOrigin.Begin); + Type t = Type.GetType ("go." + root); + + //t = CreateDynamicType (ClassName, t); + + stream.Seek (0, SeekOrigin.Begin); return t; } + + + + + static AssemblyBuilder assemblyBuilder; + static ModuleBuilder moduleBuilder; + + public static void InitDynamicAssembly () + { + AssemblyName an = new AssemblyName ("DynamicGraphicObjects"); + assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (an, AssemblyBuilderAccess.RunAndSave); + moduleBuilder = assemblyBuilder.DefineDynamicModule ("MainModule"); + } + + public static void TerminateDynamicAssembly () + { + } + + public static CodeCompileUnit CompileUnit; + public static CodeTypeDeclaration GOTypeDecl; + + public static CodeTypeDeclaration GenCodeType (string newTypeName, Type baseType) + { + CompileUnit = new CodeCompileUnit (); + CodeNamespace cns = null; + + int idxLastDot = newTypeName.LastIndexOf ('.'); + string typeName = newTypeName; + if (idxLastDot < 0) + cns = new CodeNamespace ("go"); + else { + typeName = newTypeName.Substring (idxLastDot + 1); + cns = new CodeNamespace (newTypeName.Substring (0, idxLastDot)); + } + CompileUnit.Namespaces.Add (new CodeNamespace ()); + CompileUnit.Namespaces.Add (cns); + CompileUnit.Namespaces [0].Imports.Add (new CodeNamespaceImport ("System")); + CodeTypeDeclaration GOTypeDecl = new CodeTypeDeclaration (typeName); + GOTypeDecl.IsClass = true; + GOTypeDecl.IsPartial = true; + GOTypeDecl.TypeAttributes |= TypeAttributes.Public; + GOTypeDecl.BaseTypes.Add (baseType.Name); + cns.Types.Add (GOTypeDecl); + return GOTypeDecl; + } + + static void GenNewClassFromGOML (string path) + { + string root = null; + string newClassName = ""; + + using (Stream stream = GetStreamFromPath (path)) { + using (XmlReader reader = XmlReader.Create (stream)) { + CodeTypeDeclaration GOTypeDecl = null; + CodeConstructor constructor = null; + + CodeExpression curRef = null; + Type curType = null; + Stack curRefStack = new Stack (); + Stack curTypeStack = new Stack (); + + int arrayIndex = -1; + int localVarCpt = 0; + + while (reader.Read ()) { + switch (reader.NodeType) { + case XmlNodeType.Element: + if (string.IsNullOrEmpty (root)) { + //create the new base class + // first element is the root element + root = reader.Name; + newClassName = reader.GetAttribute ("Class"); + if (string.IsNullOrEmpty (newClassName)) { + if (path.StartsWith ("#")) + newClassName = Path.GetFileNameWithoutExtension (path.Substring (1)); + else + newClassName = Path.GetFileNameWithoutExtension (path); + } + curType = Type.GetType ("go." + root); + + GOTypeDecl = GenCodeType (newClassName, curType); + // Declares a constructor. + constructor = new CodeConstructor (); + constructor.Attributes = MemberAttributes.Public; + GOTypeDecl.Members.Add (constructor); + + curRef = new CodeThisReferenceExpression (); + } else if (reader.Name == "Template") { + }else{ + Type childType = Type.GetType ("go." + reader.Name); + localVarCpt++; + string localVarName = childType.Name + localVarCpt; + constructor.Statements.Add ( + new CodeVariableDeclarationStatement ( + childType, + localVarName, + new CodeObjectCreateExpression (childType) + ) + ); + if (curType == typeof(go.Container) || curType.IsSubclassOf (typeof(go.Container))) { + constructor.Statements.Add ( + new CodeMethodInvokeExpression ( + curRef, + "SetChild", + new CodeVariableReferenceExpression (localVarName) + ) + ); + } else if (curType == typeof(go.Group) || curType.IsSubclassOf (typeof(go.Group))) { + constructor.Statements.Add ( + new CodeMethodInvokeExpression (curRef, "addChild", + new CodeVariableReferenceExpression (localVarName) + ) + ); + } + curTypeStack.Push (curType); + curRefStack.Push (curRef); + curRef = new CodeVariableReferenceExpression (localVarName); + curType = childType; + } + while (reader.MoveToNextAttribute ()) { + string attName = reader.Name; + string attValue = reader.Value; + + if (string.IsNullOrEmpty (attValue)) + continue; + + MemberInfo mi = curType.GetMember (attName).FirstOrDefault (); + if (mi == null) { + Debug.WriteLine (Interface.CurrentGOMLPath + "=>GOML: Unknown attribute in " + curType.ToString () + " : " + attName); + continue; + } + if (mi.MemberType == MemberTypes.Event) { + //TODO: handle events + continue; + } + if (mi.MemberType == MemberTypes.Property) { + PropertyInfo pi = mi as PropertyInfo; + + if (pi.GetSetMethod () == null) { + Debug.WriteLine (Interface.CurrentGOMLPath + "=>GOML: Read only property in " + curType.ToString () + " : " + attName); + continue; + } + + if (attValue.StartsWith("{")) { + if (Interface.DontResoveGOML) + continue; + //binding + if (!attValue.EndsWith("}")) + throw new Exception (string.Format("GOML:Malformed binding: {0}", attValue)); + + string strBinding = attValue.Substring (1, attValue.Length - 2); + + continue; + } + + CodeExpression val = null; + if (pi.PropertyType == typeof(string)) { + val = new CodePrimitiveExpression (attValue); + } else if (pi.PropertyType.IsPrimitive) { + MethodInfo me = pi.PropertyType.GetMethod ("Parse", new Type[] { typeof(string) }); + val = new CodePrimitiveExpression ( + me.Invoke (null, new string[] { attValue })); + } else if (pi.PropertyType.IsEnum || (pi.PropertyType == typeof(go.Color) && Char.IsLetter (attValue [0]))) { + val = new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (pi.PropertyType), attValue); + }else if (pi.PropertyType == typeof(go.Color) || pi.PropertyType == typeof(go.Font)) { + val = new CodeCastExpression(pi.PropertyType, + new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (pi.PropertyType), + "Parse", + new CodePrimitiveExpression (attValue) + ) + ); + } else { + val = new CodeMethodInvokeExpression (new CodeTypeReferenceExpression (pi.PropertyType), + "Parse", new CodePrimitiveExpression (attValue)); + + } + constructor.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression (curRef, attName), + val + ) + ); + } + } + reader.MoveToElement (); + if (reader.IsEmptyElement) { + curType = curTypeStack.Pop (); + curRef = curRefStack.Pop (); + } + break; + case XmlNodeType.EndElement: + if (curTypeStack.Count < 1)//GOML last closing tag + break; + curType = curTypeStack.Pop (); + curRef = curRefStack.Pop (); + if (curType.IsSubclassOf (typeof(go.Container))) + arrayIndex = -1; + break; + } + } + } + } + + + + + GenerateCSharpCode (CompileUnit, path + ".cs"); + } + + static void GenerateCSharpCode (CodeCompileUnit codeBase, string file) + { + CodeDomProvider codeDomProvider = new CSharpCodeProvider (); + //On définit les options de génération de code + CodeGeneratorOptions options = new CodeGeneratorOptions (); + //On demande a ce que le code généré soit dans le même ordre que le code inséré + options.VerbatimOrder = false; + //options.BracingStyle = "C"; + //options.BracingStyle = "C"; + options.ElseOnClosing = true; + options.BlankLinesBetweenMembers = false; + + using (IndentedTextWriter itw = new IndentedTextWriter (new StreamWriter (file, false), "\t")) { + //On demande la génération proprement dite + codeDomProvider.GenerateCodeFromCompileUnit (codeBase, itw, options); + itw.Flush (); + } + Console.WriteLine ("C# code generated: " + file); + } + + public static Type CreateDynamicType (string newTypeName, Type baseType) + { + if (moduleBuilder == null) + InitDynamicAssembly (); + TypeBuilder tb = moduleBuilder.DefineType (newTypeName + , TypeAttributes.Public | + TypeAttributes.Class | + TypeAttributes.AutoClass | + TypeAttributes.AnsiClass | + TypeAttributes.BeforeFieldInit | + TypeAttributes.AutoLayout + , baseType); + + ConstructorBuilder constructor = tb.DefineDefaultConstructor (MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); + + ConstructorInfo cn = typeof(XmlRootAttribute).GetConstructor (new Type[] { typeof(string) }); + CustomAttributeBuilder cab = new CustomAttributeBuilder (cn, new object[] { baseType.Name }); + + tb.SetCustomAttribute (cab); + + + + + Type tmp = tb.CreateType (); + //assemblyBuilder.Save ("newAssembly.dll",PortableExecutableKinds.ILOnly,ImageFileMachine.I386); + return tmp; + } + public static string CurrentGOMLPath; - public static GraphicObject Load(string path, object hostClass = null, bool resolveGOML = true) - { + + public static GraphicObject Load (string path, object hostClass = null, bool resolveGOML = true) + { +// GenNewClassFromGOML (path); +// return null; CurrentGOMLPath = path; using (Stream stream = GetStreamFromPath (path)) { return Load(stream, GetTopContainerOfGOMLStream(stream), hostClass, resolveGOML); } CurrentGOMLPath = ""; } - public static GraphicObject Load(Stream stream, Type type, object hostClass = null, bool resolve = true) + + public static GraphicObject Load (Stream stream, Type type, object hostClass = null, bool resolve = true) { #if DEBUG_LOAD_TIME Stopwatch loadingTime = new Stopwatch (); @@ -154,16 +434,16 @@ namespace go GraphicObject result; - XmlSerializerNamespaces xn = new XmlSerializerNamespaces(); - xn.Add("", ""); + XmlSerializerNamespaces xn = new XmlSerializerNamespaces (); + xn.Add ("", ""); //prevent unused ref in References created by xmlSerializer Interface.DontResoveGOML = true; - XmlSerializer xs = new XmlSerializer(type); + XmlSerializer xs = new XmlSerializer (type); Interface.DontResoveGOML = false; - GOMLResolutionStack.Push(new List()); + GOMLResolutionStack.Push (new List ()); - result = (GraphicObject)xs.Deserialize(stream); - result.DataSource = hostClass; + result = (GraphicObject)xs.Deserialize (stream); + //result.DataSource = hostClass; if (hostClass == null) { GOMLResolutionStack.Pop (); @@ -175,24 +455,23 @@ namespace go #if DEBUG_LOAD_TIME loadingTime.Stop (); - Debug.WriteLine("GOML Loading ({2}): {0} ticks \t, {1} ms", - loadingTime.ElapsedTicks, - loadingTime.ElapsedMilliseconds, - CurrentGOMLPath); + Debug.WriteLine ("GOML Loading ({2}): {0} ticks \t, {1} ms", + loadingTime.ElapsedTicks, + loadingTime.ElapsedMilliseconds, + CurrentGOMLPath); #endif return result; } - public static void resolveGOML(object hostClass) + public static void resolveGOML (object hostClass) { - foreach (DynAttribute es in GOMLResolver) - { + foreach (DynAttribute es in GOMLResolver) { // if (string.IsNullOrEmpty(es.Value)) // continue; Type dstType = es.Source.GetType (); - MemberInfo miTarget = dstType.GetMember (es.MemberName).FirstOrDefault(); + MemberInfo miTarget = dstType.GetMember (es.MemberName).FirstOrDefault (); if (miTarget == null) { Debug.WriteLine ("'{0}' Member not found in '{1}' type.", es.MemberName, dstType.ToString ()); @@ -210,7 +489,7 @@ namespace go if (mi == null) { //TODO: hack to have it work, hostClass and dataSource should be clearly separated mi = OpenTKGameWindow.currentWindow.GetType ().GetMethod (es.Value, BindingFlags.NonPublic | BindingFlags.Public - | BindingFlags.Instance); + | BindingFlags.Instance); if (mi == null) { Debug.WriteLine ("Handler Method not found: " + es.Value); continue; @@ -223,15 +502,16 @@ namespace go Delegate del = Delegate.CreateDelegate (ei.EventHandlerType, effectiveHostClass, mi); - addHandler.Invoke(es.Source, new object[] {del}); + addHandler.Invoke (es.Source, new object[] { del }); } } else { CompilerServices.ResolveBinding (es, hostClass); } } - GOMLResolutionStack.Pop(); + GOMLResolutionStack.Pop (); } + #endregion } } -- 2.47.3