<Compile Include="src\rsvg\RsvgSharp.SizeFuncNative.cs" />
<Compile Include="src\rsvg\SizeFunc.cs" />
<Compile Include="src\MouseCursorChangedEventArgs.cs" />
- <Compile Include="src\GraphicObjects\IBindable.cs" />
<Compile Include="src\Input\KeyPressEventArgs.cs" />
<Compile Include="src\Configuration.cs" />
<Compile Include="src\Measure.cs" />
<Compile Include="src\StyleReader.cs" />
<Compile Include="src\IMLStream.cs" />
<Compile Include="src\GraphicObjects\DirectoryView.cs" />
+ <Compile Include="src\IMLInstantiatorBuilder.cs" />
+ <Compile Include="src\Instantiator.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<?xml version="1.0"?>
-<HorizontalStack Background="{./Background}" Margin="1" Spacing="1" Height="{./HeightPolicy}" Width="{./WidthPolicy}">
- <Image Margin="2" Width="14" Height="14" Path="#Crow.Images.Icons.checkbox.svg"
- SvgSub="{./IsChecked}"/>
- <Label Font="{./Font}" Text="{./Caption}" Height="{./HeightPolicy}" Width="{./WidthPolicy}"/>
-</HorizontalStack>
\ No newline at end of file
+
+ <Label/>
this.KeyDown += KeyboardKeyDown1;
testFiles = new string [] { @"Interfaces/Divers/welcome.crow" };
- testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/GraphicObject", "*.crow")).ToArray ();
- //testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/basicTests", "*.crow")).ToArray ();
+ testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/basicTests", "*.crow")).ToArray ();
testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Container", "*.crow")).ToArray ();
+ testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/GraphicObject", "*.crow")).ToArray ();
testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Group", "*.crow")).ToArray ();
testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Stack", "*.crow")).ToArray ();
testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Splitter", "*.crow")).ToArray ();
<?xml version="1.0"?>
-<Label Margin="50" Width="50%" Height="50%" TextAlignment="BottomRight" Background="Mantis"/>
-<!--<Container Background="Green" Margin="10" Width="Fit" Height="Fit">
- <GraphicObject Margin="10" Width="{../WidthPolicy}" Height="{../HeightPolicy}" Background="Red"
- MinimumSize="50,50"/>
-</Container>-->
\ No newline at end of file
+<CheckBox/>
\ No newline at end of file
public string DynMethodId {
get { return dynMethodId; }
}
+ public Type SourceType {
+ get { return Source == null ? null
+ : Source.Instance == null ? null
+ : Source.Instance.GetType();}
+ }
public bool Resolved {
get { return resolved; }
}
if (Target.TryFindMember (memberName)) {
- if (TwoWayBinding) {
- IBindable source = Target.Instance as IBindable;
- if (source == null)
- throw new Exception (Source.Instance + " does not implement IBindable for 2 way bindings");
- source.Bindings.Add (new Binding (Target, Source));
- }
+ if (TwoWayBinding)
+ Interface.RegisterBinding (new Binding (Target, Source));
}
#if DEBUG_BINDING
else
using System.Linq;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Xml;
namespace Crow
{
public static class CompilerServices
{
+ public static void BuildInstanciator(IMLInstantiatorBuilder builder, Type crowType){
+ string tmpXml = builder.ReadOuterXml ();
+
+ builder.il.Emit (OpCodes.Ldloc_0);//save current go onto the stack if child has to be added
+
+ if (typeof(TemplatedControl).IsAssignableFrom (crowType)) {
+ //if its a template, first read template elements
+ using (IMLInstantiatorBuilder reader = new IMLInstantiatorBuilder (builder.il, tmpXml)) {
+
+ string template = reader.GetAttribute ("Template");
+
+ bool inlineTemplate = false;
+ if (string.IsNullOrEmpty (template)) {
+ reader.Read ();
+
+ while (reader.Read ()) {
+ if (!reader.IsStartElement ())
+ continue;
+ if (reader.Name == "Template") {
+ inlineTemplate = true;
+ reader.Read ();
+
+ readChildren (reader, crowType);
+ continue;
+ }
+ }
+ if (!inlineTemplate) {
+ DefaultTemplate dt = (DefaultTemplate)crowType.GetCustomAttributes (typeof(DefaultTemplate), true).FirstOrDefault();
+ template = dt.Path;
+ }
+ }
+ if (!inlineTemplate) {
+ reader.il.Emit (OpCodes.Ldloc_0);//Load this templateControl ref
+
+ reader.il.Emit (OpCodes.Ldstr, template); //Load template path string
+ reader.il.Emit (OpCodes.Callvirt,//call Interface.Load(path)
+ typeof(Interface).GetMethod ("Load", BindingFlags.Static | BindingFlags.Public));
+ reader.il.Emit (OpCodes.Callvirt,//add child
+ typeof(PrivateContainer).GetMethod ("SetChild", BindingFlags.Instance | BindingFlags.NonPublic));
+ }
+ }
+ }
+
+ using (IMLInstantiatorBuilder reader = new IMLInstantiatorBuilder(builder.il,tmpXml)){
+ reader.Read ();
+
+ if (reader.HasAttributes) {
+ string style = reader.GetAttribute ("Style");
+ if (!string.IsNullOrEmpty (style)) {
+ PropertyInfo pi = crowType.GetProperty ("Style");
+ CompilerServices.EmitSetValue (reader.il, pi, style);
+ }
+ }
+ if (reader.HasAttributes) {
+ reader.il.Emit (OpCodes.Ldloc_0);
+ reader.il.Emit (OpCodes.Callvirt, typeof(GraphicObject).GetMethod ("loadDefaultValues"));
+
+ while (reader.MoveToNextAttribute ()) {
+ if (reader.Name == "Style")
+ continue;
+
+ PropertyInfo pi = crowType.GetProperty (reader.Name);
+
+ if (pi == null)
+ throw new Exception ("Member '" + reader.Name + "' not found in " + crowType.Name);
+
+ CompilerServices.EmitSetValue (reader.il, pi, reader.Value);
+
+ }
+ reader.MoveToElement ();
+ }
+
+ if (reader.IsEmptyElement) {
+ reader.il.Emit (OpCodes.Pop);//pop saved ref to current object
+ return;
+ }
+
+ readChildren (reader, crowType);
+ }
+ builder.il.Emit (OpCodes.Pop);//pop saved ref to current object
+ }
+ static void readChildren(IMLInstantiatorBuilder reader, Type crowType){
+ MethodInfo miAddChild = null;
+ bool endTagReached = false;
+ while (reader.Read()){
+ switch (reader.NodeType) {
+ case XmlNodeType.EndElement:
+ endTagReached = true;
+ break;
+ case XmlNodeType.Element:
+ //Templates
+
+
+ if (miAddChild == null) {
+ if (typeof(Group).IsAssignableFrom (crowType))
+ miAddChild = typeof(Group).GetMethod ("AddChild");
+ else if (typeof(Container).IsAssignableFrom (crowType))
+ miAddChild = typeof(Container).GetMethod ("SetChild");
+ else if (typeof(PrivateContainer).IsAssignableFrom (crowType))
+ miAddChild = typeof(PrivateContainer).GetMethod ("SetChild",
+ BindingFlags.Instance | BindingFlags.NonPublic);
+ }
+
+ //push current instance on stack for parenting
+ //loc_0 will be used for child
+ reader.il.Emit (OpCodes.Ldloc_0);
+
+ Type t = Type.GetType ("Crow." + reader.Name);
+ if (t == null) {
+ Assembly a = Assembly.GetEntryAssembly ();
+ foreach (Type expT in a.GetExportedTypes ()) {
+ if (expT.Name == reader.Name)
+ t = expT;
+ }
+ }
+ if (t == null)
+ throw new Exception (reader.Name + " type not found");
+
+ reader.il.Emit(OpCodes.Newobj, t.GetConstructors () [0]);
+ reader.il.Emit (OpCodes.Stloc_0);//child is now loc_0
+
+ BuildInstanciator(reader, t);
+
+ reader.il.Emit (OpCodes.Ldloc_0);//load child on stack for parenting
+ reader.il.Emit (OpCodes.Callvirt, miAddChild);
+ reader.il.Emit (OpCodes.Stloc_0); //reset local to current go
+ reader.il.Emit (OpCodes.Ldloc_0);//save current go onto the stack if child has to be added
+ break;
+ }
+ if (endTagReached)
+ break;
+ }
+ }
+ public static void EmitSetValue(ILGenerator il, PropertyInfo pi, object val){
+ il.Emit (OpCodes.Ldloc_0);
+
+ if (val == null) {
+ il.Emit (OpCodes.Ldnull);
+ il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
+ return;
+ }
+ Type dvType = val.GetType ();
+
+ if (dvType.IsValueType) {
+ if (pi.PropertyType.IsValueType) {
+ if (pi.PropertyType.IsEnum) {
+ if (pi.PropertyType != dvType)
+ throw new Exception ("Enum mismatch in default values: " + pi.PropertyType.FullName);
+ il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val));
+ } else {
+ switch (Type.GetTypeCode (dvType)) {
+ case TypeCode.Boolean:
+ if ((bool)val == true)
+ il.Emit (OpCodes.Ldc_I4_1);
+ else
+ il.Emit (OpCodes.Ldc_I4_0);
+ break;
+ // case TypeCode.Empty:
+ // break;
+ // case TypeCode.Object:
+ // break;
+ // case TypeCode.DBNull:
+ // break;
+ // case TypeCode.SByte:
+ // break;
+ // case TypeCode.Decimal:
+ // break;
+ // case TypeCode.DateTime:
+ // break;
+ case TypeCode.Char:
+ il.Emit (OpCodes.Ldc_I4, Convert.ToChar (val));
+ break;
+ case TypeCode.Byte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val));
+ break;
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ il.Emit (OpCodes.Ldc_I4, Convert.ToUInt32 (val));
+ break;
+ case TypeCode.Int64:
+ il.Emit (OpCodes.Ldc_I8, Convert.ToInt64 (val));
+ break;
+ case TypeCode.UInt64:
+ il.Emit (OpCodes.Ldc_I8, Convert.ToUInt64 (val));
+ break;
+ case TypeCode.Single:
+ il.Emit (OpCodes.Ldc_R4, Convert.ToSingle (val));
+ break;
+ case TypeCode.Double:
+ il.Emit (OpCodes.Ldc_R8, Convert.ToDouble (val));
+ break;
+ case TypeCode.String:
+ il.Emit (OpCodes.Ldstr, Convert.ToString (val));
+ break;
+ default:
+ il.Emit (OpCodes.Pop);
+ return;
+ }
+ }
+ } else
+ throw new Exception ("Expecting valuetype in default values for: " + pi.Name);
+ }else{
+ //surely a class or struct
+ if (dvType != typeof(string))
+ throw new Exception ("Expecting String in default values for: " + pi.Name);
+ if (pi.PropertyType == typeof(string))
+ il.Emit (OpCodes.Ldstr, Convert.ToString (val));
+ else if (pi.PropertyType.IsEnum) {
+ MethodInfo miParse = typeof(Enum).GetMethod
+ ("Parse", BindingFlags.Static | BindingFlags.Public,
+ Type.DefaultBinder, new Type [] {typeof (Type), typeof (string), typeof (bool)}, null);
+
+ if (miParse == null)
+ throw new Exception ("Enum Parse method not found");
+
+ //load type of enum
+ il.Emit(OpCodes.Ldtoken, pi.PropertyType);
+ il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new
+ Type[1]{typeof(RuntimeTypeHandle)}));
+ //load enum value name
+ il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:is this convert required?
+ //load false
+ il.Emit (OpCodes.Ldc_I4_0);
+ il.Emit (OpCodes.Callvirt, miParse);
+
+ if (miParse.ReturnType != pi.PropertyType)
+ il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
+ } else {
+ MethodInfo miParse = pi.PropertyType.GetMethod
+ ("Parse", BindingFlags.Static | BindingFlags.Public,
+ Type.DefaultBinder, new Type [] {typeof (string)},null);
+ if (miParse == null)
+ throw new Exception ("no Parse method found for: " + pi.PropertyType.FullName);
+
+ il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:is this convert required?
+ il.Emit (OpCodes.Callvirt, miParse);
+
+ if (miParse.ReturnType != pi.PropertyType)
+ il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
+ }
+ }
+ il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
+ }
public static void ResolveBindings (List<Binding> Bindings)
{
if (Bindings == null)
using System.ComponentModel;
using System.Linq;
using System.Threading;
+using System.Diagnostics;
namespace Crow
{
get { return child; }
set { child = value; }
}
- public virtual T SetChild<T> (T _child)
+ public virtual void SetChild(GraphicObject _child)
{
- return base.SetChild (_child);
+ Debug.WriteLine ("container setChild");
+ base.SetChild (_child);
}
#region IXmlSerializable
namespace Crow
{
- public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange, ICloneable, IBindable
+ public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange, ICloneable
{
- #region IBindable implementation
- List<Binding> bindings = new List<Binding> ();
- public List<Binding> Bindings {
- get { return bindings; }
- }
-
- #endregion
-
internal static ulong currentUid = 0;
internal ulong uid = 0;
#endregion
/// <summary> Loads the default values from XML attributes default </summary>
- protected virtual void loadDefaultValues()
+ public void loadDefaultValues()
{
#if DEBUG_LOAD
Debug.WriteLine ("LoadDefValues for " + this.ToString ());
typeof(void),new Type[] {typeof(object)},thisType,true);
il = dm.GetILGenerator(256);
-
+ il.DeclareLocal(typeof(GraphicObject));
il.Emit(OpCodes.Nop);
+ //set local GraphicObject to root object passed as 1st argument
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Stloc_0);
- foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
- string name = "";
- object defaultValue = null;
-
- #region retrieve custom attributes
+ foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
if (pi.GetSetMethod () == null)
continue;
-
- XmlIgnoreAttribute xia = (XmlIgnoreAttribute)pi.GetCustomAttribute (typeof(XmlIgnoreAttribute));
- if (xia != null)
+ object defaultValue;
+ if (!getDefaultValue (pi, styling, out defaultValue))
continue;
- XmlAttributeAttribute xaa = (XmlAttributeAttribute)pi.GetCustomAttribute (typeof(XmlAttributeAttribute));
- if (xaa != null) {
- if (string.IsNullOrEmpty (xaa.AttributeName))
- name = pi.Name;
- else
- name = xaa.AttributeName;
- }
- int styleIndex = -1;
- if (styling.Count > 0){
- for (int i = 0; i < styling.Count; i++) {
- if (styling[i].ContainsKey (name)){
- styleIndex = i;
- break;
- }
- }
- }
- if (styleIndex >= 0){
- if (pi.PropertyType.IsEnum)//maybe should be in parser..
- defaultValue = Enum.Parse(pi.PropertyType, (string)styling[styleIndex] [name], true);
- else
- defaultValue = styling[styleIndex] [name];
- }else {
- DefaultValueAttribute dv = (DefaultValueAttribute)pi.GetCustomAttribute (typeof (DefaultValueAttribute));
- if (dv == null)
- continue;
- defaultValue = dv.Value;
- }
- #endregion
-
- il.Emit (OpCodes.Ldarg_0);
-
- if (defaultValue == null) {
- il.Emit (OpCodes.Ldnull);
- il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
- continue;
- }
- Type dvType = defaultValue.GetType ();
-
- if (dvType.IsValueType) {
- if (pi.PropertyType.IsValueType) {
- if (pi.PropertyType.IsEnum) {
- if (pi.PropertyType != dvType)
- throw new Exception ("Enum mismatch in default values: " + pi.PropertyType.FullName);
- il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (defaultValue));
- } else {
- switch (Type.GetTypeCode (dvType)) {
- case TypeCode.Boolean:
- if ((bool)defaultValue == true)
- il.Emit (OpCodes.Ldc_I4_1);
- else
- il.Emit (OpCodes.Ldc_I4_0);
- break;
-// case TypeCode.Empty:
-// break;
-// case TypeCode.Object:
-// break;
-// case TypeCode.DBNull:
-// break;
-// case TypeCode.SByte:
-// break;
-// case TypeCode.Decimal:
-// break;
-// case TypeCode.DateTime:
-// break;
- case TypeCode.Char:
- il.Emit (OpCodes.Ldc_I4, Convert.ToChar (defaultValue));
- break;
- case TypeCode.Byte:
- case TypeCode.Int16:
- case TypeCode.Int32:
- il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (defaultValue));
- break;
- case TypeCode.UInt16:
- case TypeCode.UInt32:
- il.Emit (OpCodes.Ldc_I4, Convert.ToUInt32 (defaultValue));
- break;
- case TypeCode.Int64:
- il.Emit (OpCodes.Ldc_I8, Convert.ToInt64 (defaultValue));
- break;
- case TypeCode.UInt64:
- il.Emit (OpCodes.Ldc_I8, Convert.ToUInt64 (defaultValue));
- break;
- case TypeCode.Single:
- il.Emit (OpCodes.Ldc_R4, Convert.ToSingle (defaultValue));
- break;
- case TypeCode.Double:
- il.Emit (OpCodes.Ldc_R8, Convert.ToDouble (defaultValue));
- break;
- case TypeCode.String:
- il.Emit (OpCodes.Ldstr, Convert.ToString (defaultValue));
- break;
- default:
- il.Emit (OpCodes.Pop);
- continue;
- }
- }
- } else
- throw new Exception ("Expecting valuetype in default values for: " + pi.Name);
- }else{
- //surely a class or struct
- if (dvType != typeof(string))
- throw new Exception ("Expecting String in default values for: " + pi.Name);
- if (pi.PropertyType == typeof (string))
- il.Emit (OpCodes.Ldstr, Convert.ToString (defaultValue));
- else {
- MethodInfo miParse = pi.PropertyType.GetMethod
- ("Parse", BindingFlags.Static | BindingFlags.Public,
- Type.DefaultBinder, new Type [] {typeof (string)},null);
- if (miParse == null)
- throw new Exception ("no Parse method found for: " + pi.PropertyType.FullName);
-
- il.Emit (OpCodes.Ldstr, Convert.ToString (defaultValue));
- il.Emit (OpCodes.Callvirt, miParse);
-
- if (miParse.ReturnType != pi.PropertyType)
- il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
- }
- }
- il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
+ CompilerServices.EmitSetValue (il, pi, defaultValue);
}
il.Emit(OpCodes.Ret);
#endregion
try {
- Interface.DefaultValuesLoader[styleKey] = (Interface.loadDefaultInvoker)dm.CreateDelegate(typeof(Interface.loadDefaultInvoker));
+ Interface.DefaultValuesLoader[styleKey] = (Interface.LoaderInvoker)dm.CreateDelegate(typeof(Interface.LoaderInvoker));
Interface.DefaultValuesLoader[styleKey] (this);
} catch (Exception ex) {
throw new Exception ("Error applying style <" + styleKey + ">:", ex);
}
}
+ bool getDefaultValue(PropertyInfo pi, List<Dictionary<string, object>> styling,
+ out object defaultValue){
+ defaultValue = null;
+ string name = "";
+
+ XmlIgnoreAttribute xia = (XmlIgnoreAttribute)pi.GetCustomAttribute (typeof(XmlIgnoreAttribute));
+ if (xia != null)
+ return false;
+ XmlAttributeAttribute xaa = (XmlAttributeAttribute)pi.GetCustomAttribute (typeof(XmlAttributeAttribute));
+ if (xaa != null) {
+ if (string.IsNullOrEmpty (xaa.AttributeName))
+ name = pi.Name;
+ else
+ name = xaa.AttributeName;
+ }
+
+ int styleIndex = -1;
+ if (styling.Count > 0){
+ for (int i = 0; i < styling.Count; i++) {
+ if (styling[i].ContainsKey (name)){
+ styleIndex = i;
+ break;
+ }
+ }
+ }
+ if (styleIndex >= 0){
+ if (pi.PropertyType.IsEnum)//maybe should be in parser..
+ defaultValue = Enum.Parse(pi.PropertyType, (string)styling[styleIndex] [name], true);
+ else
+ defaultValue = styling[styleIndex] [name];
+ }else {
+ DefaultValueAttribute dv = (DefaultValueAttribute)pi.GetCustomAttribute (typeof (DefaultValueAttribute));
+ if (dv == null)
+ return false;
+ defaultValue = dv.Value;
+ }
+ return true;
+ }
+
public virtual GraphicObject FindByName(string nameToFind){
return string.Equals(nameToFind, _name, StringComparison.Ordinal) ? this : null;
if (Width == Measure.Fit || Height == Measure.Fit)
RegisterForLayouting (LayoutingType.Sizing);
else if (RegisteredLayoutings == LayoutingType.None)
- Interface.CurrentInterface.EnqueueForRepaint (this);
+ CurrentInterface.EnqueueForRepaint (this);
}
/// <summary> query an update of the content, a redraw </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
{
bmp = null;
if (RegisteredLayoutings == LayoutingType.None)
- Interface.CurrentInterface.EnqueueForRepaint (this);
+ CurrentInterface.EnqueueForRepaint (this);
}
+ public Interface CurrentInterface {
+ get {
+ ILayoutable tmp = this.Parent;
+ while (tmp != null) {
+ if (tmp is Interface)
+ return tmp as Interface;
+ tmp = tmp.Parent;
+ }
+ return null;
+ }
+ }
+
#region Layouting
#if DEBUG_LAYOUTING
}
#region Binding
- public void BindMember(string _member, string _expression){
- Bindings.Add(new Binding (this, _member, _expression));
- }
public virtual void ResolveBindings()
{
- if (Bindings.Count == 0)
- return;
- #if DEBUG_BINDING
- Debug.WriteLine ("Resolve Bindings => " + this.ToString ());
- #endif
-
- CompilerServices.ResolveBindings (Bindings);
+// if (Bindings.Count == 0)
+// return;
+// #if DEBUG_BINDING
+// Debug.WriteLine ("Resolve Bindings => " + this.ToString ());
+// #endif
+//
+// CompilerServices.ResolveBindings (Bindings);
}
/// <summary>
/// </summary>
public virtual void ClearBinding(){
//dont clear binding if dataSource is not null,
- foreach (Binding b in Bindings) {
- try {
- if (!b.Resolved)
- continue;
- //cancel compiled events
- if (b.Target == null){
- continue;
- #if DEBUG_BINDING
- Debug.WriteLine("Clear binding canceled for => " + b.ToString());
- #endif
- }
- if (b.Target.Instance != DataSource){
- #if DEBUG_BINDING
- Debug.WriteLine("Clear binding canceled for => " + b.ToString());
- #endif
- continue;
- }
- #if DEBUG_BINDING
- Debug.WriteLine("ClearBinding => " + b.ToString());
- #endif
- if (string.IsNullOrEmpty (b.DynMethodId)) {
- b.Resolved = false;
- if (b.Source.Member.MemberType == MemberTypes.Event)
- removeEventHandler (b);
- //TODO:check if full reset is necessary
- continue;
- }
- MemberReference mr = null;
- if (b.Target == null)
- mr = b.Source;
- else
- mr = b.Target;
- Type dataSourceType = mr.Instance.GetType();
- EventInfo evtInfo = dataSourceType.GetEvent ("ValueChanged");
- FieldInfo evtFi = CompilerServices.GetEventHandlerField (dataSourceType, "ValueChanged");
- MulticastDelegate multicastDelegate = evtFi.GetValue (mr.Instance) as MulticastDelegate;
- if (multicastDelegate != null) {
- foreach (Delegate d in multicastDelegate.GetInvocationList()) {
- if (d.Method.Name == b.DynMethodId)
- evtInfo.RemoveEventHandler (mr.Instance, d);
- }
- }
- b.Reset ();
- } catch (Exception ex) {
- Debug.WriteLine("\t Error: " + ex.ToString());
- }
- }
+// foreach (Binding b in Bindings) {
+// try {
+// if (!b.Resolved)
+// continue;
+// //cancel compiled events
+// if (b.Target == null){
+// continue;
+// #if DEBUG_BINDING
+// Debug.WriteLine("Clear binding canceled for => " + b.ToString());
+// #endif
+// }
+// if (b.Target.Instance != DataSource){
+// #if DEBUG_BINDING
+// Debug.WriteLine("Clear binding canceled for => " + b.ToString());
+// #endif
+// continue;
+// }
+// #if DEBUG_BINDING
+// Debug.WriteLine("ClearBinding => " + b.ToString());
+// #endif
+// if (string.IsNullOrEmpty (b.DynMethodId)) {
+// b.Resolved = false;
+// if (b.Source.Member.MemberType == MemberTypes.Event)
+// removeEventHandler (b);
+// //TODO:check if full reset is necessary
+// continue;
+// }
+// MemberReference mr = null;
+// if (b.Target == null)
+// mr = b.Source;
+// else
+// mr = b.Target;
+// Type dataSourceType = mr.Instance.GetType();
+// EventInfo evtInfo = dataSourceType.GetEvent ("ValueChanged");
+// FieldInfo evtFi = CompilerServices.GetEventHandlerField (dataSourceType, "ValueChanged");
+// MulticastDelegate multicastDelegate = evtFi.GetValue (mr.Instance) as MulticastDelegate;
+// if (multicastDelegate != null) {
+// foreach (Delegate d in multicastDelegate.GetInvocationList()) {
+// if (d.Method.Name == b.DynMethodId)
+// evtInfo.RemoveEventHandler (mr.Instance, d);
+// }
+// }
+// b.Reset ();
+// } catch (Exception ex) {
+// Debug.WriteLine("\t Error: " + ex.ToString());
+// }
+// }
}
void removeEventHandler(Binding b){
FieldInfo fiEvt = CompilerServices.GetEventHandlerField (b.Source.Instance.GetType(), b.Source.Member.Name);
return;
}
if (mi.MemberType == MemberTypes.Event) {
- this.Bindings.Add (new Binding (new MemberReference(this, mi), value));
+ Interface.RegisterBinding (new Binding (new MemberReference(this, mi), value));
return;
}
if (mi.MemberType == MemberTypes.Property) {
if (!value.EndsWith("}", StringComparison.Ordinal))
throw new Exception (string.Format("XML:Malformed binding: {0}", value));
- this.Bindings.Add (new Binding (new MemberReference(this, pi), value.Substring (1, value.Length - 2)));
+ Interface.RegisterBinding (new Binding (new MemberReference(this, pi), value.Substring (1, value.Length - 2)));
return;
}
if (pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)) != null)
}
public virtual void ReadXml (System.Xml.XmlReader reader)
{
- if (reader.HasAttributes) {
-
- style = reader.GetAttribute ("Style");
+ IMLInstantiatorBuilder ir = reader as IMLInstantiatorBuilder;
+ Type thisType = this.GetType ();
- loadDefaultValues ();
+ if (ir.HasAttributes) {
+ style = ir.GetAttribute ("Style");
+ if (!string.IsNullOrEmpty (style)) {
+ PropertyInfo pi = thisType.GetProperty ("Style");
+ CompilerServices.EmitSetValue (ir.il, pi, style);
+ }
+ }
+ if (ir.HasAttributes) {
+ ir.il.Emit (OpCodes.Ldarg_0);
+ ir.il.Emit (OpCodes.Callvirt, typeof(GraphicObject).GetMethod ("loadDefaultValues"));
- while (reader.MoveToNextAttribute ()) {
- if (reader.Name == "Style")
+ while (ir.MoveToNextAttribute ()) {
+ if (ir.Name == "Style")
continue;
- affectMember (reader.Name, reader.Value);
+ PropertyInfo pi = thisType.GetProperty (ir.Name);
+
+ if (pi == null)
+ throw new Exception ("Member '" + ir.Name + "' not found in " + thisType.Name);
+
+ CompilerServices.EmitSetValue (ir.il, pi, ir.Value);
+
}
- reader.MoveToElement ();
- }else
- loadDefaultValues ();
+ ir.MoveToElement ();
+ }
}
public virtual void WriteXml (System.Xml.XmlWriter writer)
{
}
#endregion
+
+
#region ICloneable implementation
public object Clone ()
{
/// </summary>
public virtual GraphicObject DeepClone(){
GraphicObject tmp = Clone () as GraphicObject;
- foreach (Binding b in this.bindings)
- tmp.Bindings.Add (new Binding (new MemberReference (tmp, b.Source.Member), b.Expression));
+// foreach (Binding b in this.bindings)
+// tmp.Bindings.Add (new Binding (new MemberReference (tmp, b.Source.Member), b.Expression));
return tmp;
}
}
int _rowCount;
#endregion
- public override T AddChild<T> (T child)
+ public override void AddChild (GraphicObject child)
{
- T tmp = base.AddChild (child);
+ base.AddChild (child);
this.RegisterForLayouting (LayoutingType.ArrangeChildren);
- return tmp;
}
public override void RemoveChild (GraphicObject child)
{
get { return _multiSelect; }
set { _multiSelect = value; }
}
-
-
- public virtual T AddChild<T>(T child)
- {
- GraphicObject g = child as GraphicObject;
+ public virtual void AddChild(GraphicObject g){
Children.Add(g);
- g.Parent = this as GraphicObject;
+ g.Parent = this;
g.ResolveBindings ();
g.RegisteredLayoutings = LayoutingType.None;
g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
g.LayoutChanged += OnChildLayoutChanges;
- return (T)child;
- }
+ }
public virtual void RemoveChild(GraphicObject child)
{
child.LayoutChanged -= OnChildLayoutChanges;
+++ /dev/null
-//
-// IValueChange.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2015 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-using System;
-using System.Collections.Generic;
-
-namespace Crow
-{
- public interface IBindable
- {
- List<Binding> Bindings { get; }
- object DataSource { get; set; }
- }
-}
-
//because _list total size is forced to approx size
if (_gsList.Orientation == Orientation.Horizontal) {
page.Width = Measure.Fit;
- page.BindMember ("Height", "../HeightPolicy");
+ Interface.Bindings.Add(new Binding (this, "Height", "../HeightPolicy"));
} else {
page.Height = Measure.Fit;
- page.BindMember ("Width", "../WidthPolicy");
+ Interface.Bindings.Add(new Binding (this, "Width", "../WidthPolicy"));
}
for (int i = (pageNum - 1) * itemPerPage; i < pageNum * itemPerPage; i++) {
using System.Xml.Serialization;
using System.ComponentModel;
using Cairo;
+using System.Diagnostics;
namespace Crow
{
protected GraphicObject child;
- protected virtual T SetChild<T>(T _child)
+ internal virtual void SetChild(GraphicObject _child)
{
if (child != null) {
child.RegisteredLayoutings = LayoutingType.None;
child.RegisterForLayouting (LayoutingType.Sizing);
}
+ Debug.WriteLine ("privateContainer setChild");
- return (T)_child;
}
#region GraphicObject Overrides
ScrollY = 0;
ScrollX = 0;
}
- public override T SetChild<T> (T _child)
+ public override void SetChild (GraphicObject _child)
{
GraphicObject c = child as GraphicObject;
Group g = child as Group;
if (g != null)
g.ChildrenCleared += onChildListCleared;
}
- return base.SetChild (_child);
+ base.SetChild (_child);
}
#endregion
set { }
}
- public override T AddChild<T> (T child)
+ public override void AddChild (GraphicObject child)
{
TabItem ti = child as TabItem;
if (ti == null)
SelectedTab = 0;
}
- return base.AddChild (child);
+ base.AddChild (child);
}
public override void RemoveChild (GraphicObject child)
{
--- /dev/null
+//
+// IMLReader.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2016 jp
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+using System;
+using System.Xml;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Crow
+{
+ public class IMLInstantiatorBuilder : XmlTextReader
+ {
+ public Stream ImlStream;
+ public Type RootType = null;
+
+ DynamicMethod dm = null;
+ public ILGenerator il = null;
+
+ public IMLInstantiatorBuilder (Stream stream)
+ : base(stream)
+ {
+ ImlStream = stream;
+ }
+ public IMLInstantiatorBuilder (ILGenerator ilGen, string xmlFragment)
+ : base(xmlFragment, XmlNodeType.Element,null){
+ il = ilGen;
+ }
+ /// <summary>
+ /// Inits il generator, RootType must have been read first
+ /// </summary>
+ public void InitEmitter(){
+
+ dm = new DynamicMethod("dyn_instantiator",
+ MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot,
+ CallingConventions.Standard,
+ typeof(void),new Type[] {typeof(object)}, RootType, true);
+
+ il = dm.GetILGenerator(256);
+ il.DeclareLocal(typeof(GraphicObject));
+ il.Emit(OpCodes.Nop);
+ //set local GraphicObject to root object passed as 1st argument
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Stloc_0);
+ }
+
+ /// <summary>
+ /// read first node to set GraphicObject class for loading
+ /// and let reader position on that node
+ /// </summary>
+ public Type ReadRootType ()
+ {
+ string root = "Object";
+ while (Read()) {
+ if (NodeType == XmlNodeType.Element) {
+ root = this.Name;
+ break;
+ }
+ }
+
+ Type t = Type.GetType ("Crow." + root);
+ if (t == null) {
+ Assembly a = Assembly.GetEntryAssembly ();
+ foreach (Type expT in a.GetExportedTypes ()) {
+ if (expT.Name == root)
+ t = expT;
+ }
+ }
+ RootType = t;
+ return t;
+ }
+ /// <summary>
+ /// Finalize instatiator MSIL and return LoaderInvoker delegate
+ /// </summary>
+ public Instantiator GetInstanciator(){
+ il.Emit(OpCodes.Ret);
+
+ return new Instantiator (RootType,
+ (Interface.LoaderInvoker)dm.CreateDelegate (typeof(Interface.LoaderInvoker)));
+ }
+ }
+}
+
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
+using System.Xml.Serialization;
+using System.Xml;
+using System.Collections.Generic;
+using System.Diagnostics;
namespace Crow
{
Path = path;
using (Stream stream = Interface.GetStreamFromPath (path))
stream.CopyTo (this);
- RootType = Interface.GetTopContainerOfXMLStream (this);
+ //RootType = Interface.GetTopContainerOfXMLStream (this);
}
public IMLStream(Byte[] b) : base (b){
- RootType = Interface.GetTopContainerOfXMLStream (this);
+ //RootType = Interface.GetTopContainerOfXMLStream (this);
}
/// <summary>
/// Create a graphicObject instance from the this XML stream.
Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
Seek (0, SeekOrigin.Begin);
- GraphicObject tmp = Interface.Load (this, this.RootType);
+ GraphicObject tmp = null;//Interface.Load (this, this.RootType);
Thread.CurrentThread.CurrentCulture = savedCulture;
return tmp;
--- /dev/null
+//
+// Instantiator.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2016 jp
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+using System;
+
+namespace Crow
+{
+ public class Instantiator
+ {
+ Type RootType;
+ Interface.LoaderInvoker Loader;
+ public Instantiator (Type _root, Interface.LoaderInvoker loader)
+ {
+ RootType = _root;
+ Loader = loader;
+ }
+ public GraphicObject CreateInstance(){
+ GraphicObject tmp = (GraphicObject)Activator.CreateInstance(RootType);
+ Loader (tmp);
+ return tmp;
+ }
+ }
+}
+
FontRenderingOptions.HintMetrics = HintMetrics.On;
FontRenderingOptions.HintStyle = HintStyle.Medium;
FontRenderingOptions.SubpixelOrder = SubpixelOrder.Rgb;
+
+ Thread tBindings = new Thread (BindingThread);
+ tBindings.IsBackground = true;
+ tBindings.Start ();
}
public Interface(){
Interface.CurrentInterface = this;
g.IsQueueForRedraw = true;
}
}
+ //fast compiled IML instantiators
+ public static Dictionary<String, Instantiator> Instantiators = new Dictionary<string, Instantiator>();
#region Default values and Style loading
/// Default values of properties from GraphicObjects are retrieve from XML Attributes.
/// The reflexion process used to retrieve those values being very slow, it is compiled in MSIL
/// and injected as a dynamic method referenced in the DefaultValuesLoader Dictionnary.
/// The compilation is done on the first object instancing, and is also done for custom widgets
- public delegate void loadDefaultInvoker(object instance);
- public static Dictionary<String, loadDefaultInvoker> DefaultValuesLoader = new Dictionary<string, loadDefaultInvoker>();
+ public delegate void LoaderInvoker(object instance);
+ public static Dictionary<String, LoaderInvoker> DefaultValuesLoader = new Dictionary<string, LoaderInvoker>();
public static Dictionary<string, Dictionary<string, object>> Styling;
/// <summary> parse all styling data's and build global Styling Dictionary </summary>
static void LoadStyling() {
return stream;
}
- /// <summary>
- /// Pre-read first node to set GraphicObject class for loading
- /// and reset stream position to 0
- /// </summary>
- public static Type GetTopContainerOfXMLStream (Stream stream)
- {
- string root = "Object";
- stream.Seek (0, SeekOrigin.Begin);
- using (XmlReader reader = XmlReader.Create (stream)) {
- while (reader.Read ()) {
- // first element is the root element
- if (reader.NodeType == XmlNodeType.Element) {
- root = reader.Name;
- break;
- }
- }
- }
-
- Type t = Type.GetType ("Crow." + root);
- if (t == null) {
- Assembly a = Assembly.GetEntryAssembly ();
- foreach (Type expT in a.GetExportedTypes ()) {
- if (expT.Name == root)
- t = expT;
- }
- }
-
- stream.Seek (0, SeekOrigin.Begin);
- return t;
- }
public static void Save<T> (string file, T graphicObject)
{
GraphicObject tmp = null;
try {
- using (Stream stream = GetStreamFromPath (path)) {
- tmp = Load(stream, GetTopContainerOfXMLStream(stream));
- }
+ if (!Instantiators.ContainsKey(path))
+ BuildInstaciator(path);
+ tmp = Instantiators [path].CreateInstance ();
+
} catch (Exception ex) {
throw new Exception ("Error loading <" + path + ">:", ex);
}
return tmp;
}
- internal static GraphicObject Load (Stream stream, Type type)
+ public static void BuildInstaciator (string path)
{
+ System.Globalization.CultureInfo savedCulture = Thread.CurrentThread.CurrentCulture;
+ Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
+
#if DEBUG_LOAD
Stopwatch loadingTime = new Stopwatch ();
loadingTime.Start ();
#endif
- GraphicObject result;
-
- CurrentInterface.XmlLoading = true;
-
- XmlSerializerNamespaces xn = new XmlSerializerNamespaces ();
- xn.Add ("", "");
-
- XmlSerializer xs = new XmlSerializer (type);
-
- result = (GraphicObject)xs.Deserialize (stream);
- CurrentInterface.XmlLoading = false;
+ try {
+ using (Stream stream = GetStreamFromPath (path)) {
+ using (IMLInstantiatorBuilder itr = new IMLInstantiatorBuilder (stream)){
+ itr.ReadRootType();
+ itr.InitEmitter();
+ CompilerServices.BuildInstanciator(itr, itr.RootType);
+ itr.Read();//close tag
+ Instantiators[path] = itr.GetInstanciator();
+ }
+ }
+ } catch (Exception ex) {
+ throw new Exception ("Error loading <" + path + ">:", ex);
+ }
#if DEBUG_LOAD
- FileStream fs = stream as FileStream;
- if (fs!=null)
- CurrentGOMLPath = fs.Name;
loadingTime.Stop ();
- Debug.WriteLine ("GOML Loading ({2}->{3}): {0} ticks, {1} ms",
- loadingTime.ElapsedTicks,
- loadingTime.ElapsedMilliseconds,
- CurrentGOMLPath, result.ToString());
+ Debug.WriteLine ("IML Loading '{2}' : {0} ticks, {1} ms",
+ loadingTime.ElapsedTicks, loadingTime.ElapsedMilliseconds, path);
#endif
- return result;
+ Thread.CurrentThread.CurrentCulture = savedCulture;
}
public GraphicObject LoadInterface (string path)
public List<GraphicObject> GraphicTree = new List<GraphicObject>();
+ public static List<Binding> Bindings = new List<Binding>();
+ public static void RegisterBinding (Binding b){
+ lock (Bindings)
+ Bindings.Add (b);
+ }
+ public static void BindingThread(){
+ while(true){
+ Binding[] unresolved;
+ lock (Bindings){
+ unresolved = Bindings.Where (b => !b.Resolved).ToArray ();
+ }
+ foreach (Binding ub in unresolved) {
+ if (ub.TryFindTarget ()) {
+ ub.Resolved = true;
+ Debug.WriteLine ("RESOLVED: " + ub);
+ }
+ }
+ Thread.Sleep (5);
+ }
+ }
+
public static Interface CurrentInterface;
Rectangles _redrawClip = new Rectangles();