aboutsummaryrefslogtreecommitdiffstatsci
path: root/src
diff options
context:
space:
mode:
authorjpbruyere <jp.bruyere@hotmail.com>2015-09-29 10:07:13 +0200
committerjpbruyere <jp.bruyere@hotmail.com>2015-09-29 10:07:13 +0200
commit8dcac53903c37878d54d59066eb7f80da1d62bc7 (patch)
tree577390ded6146578e0c8b0efae5da549c99c5cec /src
parentbc12a8d14fd559918c1ed97ed8f2cc5c8c9043c7 (diff)
generate c# with codedom for GOML
MonoDevelop.GOLib addin
Diffstat (limited to 'src')
-rw-r--r--src/CompilerServices/CompilerServices.cs142
-rw-r--r--src/GraphicObjects/GraphicObject.cs117
-rw-r--r--src/GraphicObjects/Group.cs2
-rw-r--r--src/GraphicObjects/PrivateContainer.cs2
-rw-r--r--src/GraphicObjects/Scroller.cs2
-rw-r--r--src/Interface.cs378
6 files changed, 534 insertions, 109 deletions
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;
+ /// <summary>
+ /// Compile events expression in GOML attributes
+ /// </summary>
+ /// <param name="es">Event binding details</param>
+ 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;
+
/// <summary>
/// Compile events expression in GOML attributes
/// </summary>
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<int> DynamicMethodIds = new List<int> ();
@@ -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 {
+// {
+// //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
- });
+ if (attValue.StartsWith("{")) {
+ if (Interface.DontResoveGOML)
continue;
- }
+ //binding
+ if (!attValue.EndsWith("}"))
+ throw new Exception (string.Format("GOML:Malformed binding: {0}", attValue));
- if (pi.PropertyType == typeof(string)) {
- pi.SetValue (this, attValue, null);
- continue;
- }
+ string strBinding = attValue.Substring (1, attValue.Length - 2);
+ Interface.GOMLResolver.Add (new DynAttribute () {
+ Source = this,
+ MemberName = attName,
+ Value = strBinding
+ });
+ continue;
+ }
- object o = null;
+ if (pi.PropertyType == typeof(string)) {
+ pi.SetValue (this, attValue, null);
+ continue;
+ }
- 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 });
- }
+ object o = null;
+
+ 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
/// <summary>
/// Graphic objects References use in dynamic delegates for binding
/// </summary>
- public static List<object> References = new List<object>();
- public static Queue<int> FreeRefIndices = new Queue<int>();
- public static void Unreference(Object o)
+ public static List<object> References = new List<object> ();
+ public static Queue<int> FreeRefIndices = new Queue<int> ();
+
+ 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);
}
+
/// <summary> register target object reference in an array for binding CIL </summary>
- 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<List<DynAttribute>> GOMLResolutionStack = new Stack<List<DynAttribute>>();
- internal static List<DynAttribute> GOMLResolver
- {
- get { return GOMLResolutionStack.Peek ();}
+ internal static Stack<List<DynAttribute>> GOMLResolutionStack = new Stack<List<DynAttribute>> ();
+
+ internal static List<DynAttribute> GOMLResolver {
+ get { return GOMLResolutionStack.Peek (); }
}
//internal static List<DynAttribute> Bindings;
- public static void Save<T>(string file, T graphicObject)
+ public static void Save<T> (string file, T graphicObject)
{
- XmlSerializerNamespaces xn = new XmlSerializerNamespaces();
- xn.Add("", "");
- XmlSerializer xs = new XmlSerializer(typeof(T));
+ 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);
+ 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;
}
+
/// <summary>
/// Pre-read first node to set GraphicObject class for loading
/// and reset stream position to 0
/// </summary>
- 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<CodeExpression> curRefStack = new Stack<CodeExpression> ();
+ Stack<Type> curTypeStack = new Stack<Type> ();
+
+ 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<DynAttribute>());
+ GOMLResolutionStack.Push (new List<DynAttribute> ());
- 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
}
}