diff options
| author | j-p <jp.bruyere@live.be> | 2016-08-11 04:20:36 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-08-11 04:20:36 +0200 |
| commit | 81eb8c7a75ffbe8b6740b2a84a9ebff75da9b393 (patch) | |
| tree | 3225277358a2bba61c4496923ba39353c942098b | |
| parent | 4d4a9116ea5c68b27f0b7c43db9682ab57738ae7 (diff) | |
| parent | 7560c0bb4a769210e289e2633ddf13d2617f8e6e (diff) | |
Merge pull request #18 from jpbruyere/BindingImprovement
Instantiator
25 files changed, 784 insertions, 313 deletions
diff --git a/Crow.csproj b/Crow.csproj index 7dde305f..07879eeb 100644 --- a/Crow.csproj +++ b/Crow.csproj @@ -134,8 +134,10 @@ <Compile Include="src\CompilerServices\MemberReference.cs" /> <Compile Include="src\CompilerServices\Bindings.cs" /> <Compile Include="src\StyleReader.cs" /> - <Compile Include="src\IMLStream.cs" /> <Compile Include="src\GraphicObjects\DirectoryView.cs" /> + <Compile Include="src\Instantiator.cs" /> + <Compile Include="src\IMLReader.cs" /> + <Compile Include="src\ItemTemplate.cs" /> </ItemGroup> <ItemGroup> <Reference Include="System" /> diff --git a/Default.style b/Default.style index f3ec0113..b21bd577 100644 --- a/Default.style +++ b/Default.style @@ -42,4 +42,7 @@ Window { } Border { Foreground = White; +} +ProgressBar { + Foreground = vgradient|0:BlueCrayola|0.5:SkyBlue|1:BlueCrayola; }
\ No newline at end of file diff --git a/Templates/MessageBox.goml b/Templates/MessageBox.goml index 4489ee6b..2468b7fc 100644 --- a/Templates/MessageBox.goml +++ b/Templates/MessageBox.goml @@ -22,7 +22,7 @@ Path="#Crow.Images.Icons.iconInfo.svg" /> <Label Font="serif, 12" Height="{./HeightPolicy}" Width="{./WidthPolicy}" Text="{./Message}" TextAlignment="Left" - Multiline="true" WordWrap="true"/> + Multiline="true" /> </HorizontalStack> <HorizontalStack Height="-1" Width="{./WidthPolicy}" Margin="3"> <GraphicObject Height="5"/> diff --git a/Tests/BasicTests.cs b/Tests/BasicTests.cs index 2a82bd23..658cddd8 100644 --- a/Tests/BasicTests.cs +++ b/Tests/BasicTests.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Linq; using System.IO; using System.Reflection; +using System.Text; +using System.Diagnostics; namespace Tests @@ -92,10 +94,10 @@ namespace Tests 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 = new string [] { @"Interfaces/Divers/welcome.crow" }; + testFiles = Directory.GetFiles (@"Interfaces/basicTests", "*.crow"); 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 (); @@ -151,14 +153,27 @@ namespace Tests if (fi == null) return; if (fi.Extension == ".crow" || fi.Extension == ".goml") { - IMLStream imls = new IMLStream (fi.FullName); + Instantiator i = new Instantiator(fi.FullName); lock (CrowInterface.UpdateMutex) { (CrowInterface.FindByName ("crowContainer") as Container).SetChild - (imls.Instance); - CurSources = imls.Source; + (i.CreateInstance()); + CurSources = i.GetImlSourcesCode(); } } } + void onImlSourceChanged(Object sender, TextChangeEventArgs e){ + Instantiator i; + try { + i = Instantiator.CreateFromImlFragment (e.Text); + } catch (Exception ex) { + Debug.WriteLine (ex); + return; + } + lock (CrowInterface.UpdateMutex) { + (CrowInterface.FindByName ("crowContainer") as Container).SetChild + (i.CreateInstance()); + } + } void onButClick(object send, MouseButtonEventArgs e) { Console.WriteLine ("button clicked:" + send.ToString()); diff --git a/Tests/Interfaces/Divers/imlEditor.crow b/Tests/Interfaces/Divers/imlEditor.crow index 527745c1..bbad04ef 100644 --- a/Tests/Interfaces/Divers/imlEditor.crow +++ b/Tests/Interfaces/Divers/imlEditor.crow @@ -15,6 +15,7 @@ <TextBox Background="White" Height="Fit" VerticalAlignment="Top" TextAlignment="TopLeft" Font="mono, 10" + TextChanged="onImlSourceChanged" Text="{CurSources}" Multiline="true"/> </Scroller> <ScrollBar Name="scrollbar1" Value="{../scroller1.ScrollY}" diff --git a/Tests/Interfaces/basicTests/0.crow b/Tests/Interfaces/basicTests/0.crow index b5c153ef..9d3948af 100755 --- a/Tests/Interfaces/basicTests/0.crow +++ b/Tests/Interfaces/basicTests/0.crow @@ -1,6 +1,2 @@ <?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 diff --git a/Tests/Interfaces/basicTests/8.crow b/Tests/Interfaces/basicTests/8.crow new file mode 100755 index 00000000..a20e1ac5 --- /dev/null +++ b/Tests/Interfaces/basicTests/8.crow @@ -0,0 +1,34 @@ +<?xml version="1.0"?> +<Slider Background="Blue" Width="100" Height="20"/> +<!--<ScrollBar Orientation="Vertical" Maximum="100" Value="10" + Width="14" Height="300"/>--> +<!--<ListBox Data="{TestList}" Width="50%" ItemTemplate="#Tests.Interfaces.colorItem.crow"> + <Template> + <Border BorderWidth="1" Height="{../HeightPolicy}" Width="{../WidthPolicy}"> + <HorizontalStack Margin="1" Height="{../../HeightPolicy}" Width="{../../WidthPolicy}" > + <Scroller Name="scroller1" Height="{../../../HeightPolicy}" Width="{../../../WidthPolicy}" + Margin="2" VerticalScrolling="true" ScrollY="{../scrollbar1.Value}" + ValueChanged="../../../_scroller_ValueChanged"> + <VerticalStack Width="{../../../../WidthPolicy}" Height="Fit" MinimumSize="10,10" + Name="List" Margin="0" + VerticalAlignment="Top" + HorizontalAlignment="Left" + LayoutChanged="../../../../_list_LayoutChanged"/> + </Scroller> + <ScrollBar Name="scrollbar1" Value="{../scroller1.ScrollY}" + Maximum="{../scroller1.MaximumScroll}" Orientation="Vertical" + Width="14" Height="{../../../HeightPolicy}" /> + </HorizontalStack> + </Border> + </Template> +</ListBox>--> +<!--<ItemTemplate> +<HorizontalStack + HorizontalAlignment="Left" + Height="Fit" Margin="1" Focusable="true" + MouseEnter="{Background=hgradient|0:DarkRed|1:Mantis}" + MouseLeave="{Background=Transparent}"> + <GraphicObject Height="12" Width="20" Background="{}" Margin="0" CornerRadius="3"/> + <Label Text="{Name}" Margin="0" Width="Stretched"/> +</HorizontalStack> +</ItemTemplate>--> diff --git a/src/CompilerServices/Bindings.cs b/src/CompilerServices/Bindings.cs index 8ece856c..64f412f6 100644 --- a/src/CompilerServices/Bindings.cs +++ b/src/CompilerServices/Bindings.cs @@ -41,6 +41,11 @@ namespace Crow 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; } @@ -123,10 +128,12 @@ namespace Crow //datasource binding object dataSource = (Source.Instance as GraphicObject).DataSource; if (dataSource == null) { + #if DEBUG_BINDING Debug.WriteLine ("\tDataSource is null => " + this.ToString()); + #endif return false; } - + Target = new MemberReference (dataSource); memberName = bindingExp [0]; } else { @@ -148,7 +155,7 @@ namespace Crow while (ptr < bindingExp.Length - 1) { if (tmpTarget == null) { #if DEBUG_BINDING - Debug.WriteLine ("\tERROR: target not found => " + this.ToString()); + Debug.WriteLine ("\tTarget not found => " + this.ToString()); #endif return false; } @@ -164,14 +171,12 @@ namespace Crow } if (tmpTarget == null) { -#if DEBUG_BINDING - Debug.WriteLine ("\tERROR: Binding Target not found => " + this.ToString()); -#endif + #if DEBUG_BINDING + Debug.WriteLine ("\tBinding Target not found => " + this.ToString()); + #endif return false; } - Target = new MemberReference (tmpTarget); - string [] bindTrg = bindingExp [ptr].Split ('.'); if (bindTrg.Length == 1) @@ -182,6 +187,14 @@ namespace Crow } else throw new Exception ("Syntax error in binding, expected 'go dot member'"); + if (tmpTarget == null) { + #if DEBUG_BINDING + Debug.WriteLine ("\tBinding Target not found => " + this.ToString()); + #endif + return false; + } + + Target = new MemberReference (tmpTarget); } if (Target.TryFindMember (memberName)) { diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index 0b69f970..d06cd29b 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -5,12 +5,136 @@ using System.Diagnostics; using System.Linq; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Xml; namespace Crow { public static class CompilerServices { + static MethodInfo miAddBinding = typeof(GraphicObject).GetMethod ("BindMember"); + + + public static void emitBindingCreation(ILGenerator il, string memberName, string expression){ + il.Emit (OpCodes.Ldloc_0); + il.Emit (OpCodes.Ldstr, memberName); + il.Emit (OpCodes.Ldstr, expression); + il.Emit (OpCodes.Callvirt, miAddBinding); + } + + 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) diff --git a/src/GraphicObjects/Container.cs b/src/GraphicObjects/Container.cs index 69e3a3b4..fb4a7834 100644 --- a/src/GraphicObjects/Container.cs +++ b/src/GraphicObjects/Container.cs @@ -25,9 +25,9 @@ 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); + base.SetChild (_child); } #region IXmlSerializable diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index 8966acf6..88166fe6 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -513,7 +513,7 @@ namespace Crow #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 ()); @@ -581,151 +581,70 @@ namespace Crow 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) - 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 ()); + object defaultValue; + if (!getDefaultValue (pi, styling, out defaultValue)) 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; @@ -757,6 +676,18 @@ namespace Crow if (RegisteredLayoutings == LayoutingType.None) Interface.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 diff --git a/src/GraphicObjects/Grid.cs b/src/GraphicObjects/Grid.cs index 525827e0..ed0cd986 100644 --- a/src/GraphicObjects/Grid.cs +++ b/src/GraphicObjects/Grid.cs @@ -29,11 +29,10 @@ namespace Crow 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) { diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index a6ca5758..4c8d0537 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -38,19 +38,14 @@ namespace Crow 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; diff --git a/src/GraphicObjects/ListBox.cs b/src/GraphicObjects/ListBox.cs index 58d41e0b..ab349ed4 100644 --- a/src/GraphicObjects/ListBox.cs +++ b/src/GraphicObjects/ListBox.cs @@ -119,7 +119,7 @@ namespace Crow if (ItemTemplates == null) ItemTemplates = new Dictionary<string, ItemTemplate> (); if (!ItemTemplates.ContainsKey ("default")) - ItemTemplates["default"] = new ItemTemplate (ItemTemplate); + ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate); for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) { if (cancelLoading) @@ -164,16 +164,16 @@ namespace Crow return; GraphicObject g = null; - ItemTemplate itemStream = null; + ItemTemplate iTemp = null; Type dataType = data [i].GetType (); if (ItemTemplates.ContainsKey (dataType.FullName)) - itemStream = ItemTemplates [dataType.FullName]; + iTemp = ItemTemplates [dataType.FullName]; else - itemStream = ItemTemplates ["default"]; + iTemp = ItemTemplates ["default"]; lock (Interface.CurrentInterface.LayoutMutex) { - g = itemStream.Instance; + g = iTemp.CreateInstance(); page.AddChild (g); g.DataSource = data [i]; } @@ -190,8 +190,8 @@ namespace Crow }else g.MouseClick += itemClick; - if (itemStream.Expand != null && g is Expandable) { - (g as Expandable).Expand += itemStream.Expand; + if (iTemp.Expand != null && g is Expandable) { + (g as Expandable).Expand += iTemp.Expand; } //g.LogicalParent = this; } diff --git a/src/GraphicObjects/PrivateContainer.cs b/src/GraphicObjects/PrivateContainer.cs index 8793ba45..a6f52f29 100644 --- a/src/GraphicObjects/PrivateContainer.cs +++ b/src/GraphicObjects/PrivateContainer.cs @@ -47,7 +47,7 @@ namespace Crow protected GraphicObject child; - protected virtual T SetChild<T>(T _child) + internal virtual void SetChild(GraphicObject _child) { if (child != null) { @@ -67,8 +67,6 @@ namespace Crow child.RegisteredLayoutings = LayoutingType.None; child.RegisterForLayouting (LayoutingType.Sizing); } - - return (T)_child; } #region GraphicObject Overrides diff --git a/src/GraphicObjects/ProgressBar.cs b/src/GraphicObjects/ProgressBar.cs index e3f778bf..6e1ce404 100644 --- a/src/GraphicObjects/ProgressBar.cs +++ b/src/GraphicObjects/ProgressBar.cs @@ -9,7 +9,7 @@ using System.ComponentModel; namespace Crow { - [Serializable] + public class ProgressBar : NumericControl { #region CTOR @@ -22,12 +22,6 @@ namespace Crow } #region GraphicObject overrides - [XmlAttributeAttribute()][DefaultValue("vgradient|0:BlueCrayola|0,5:SkyBlue|1:BlueCrayola")] - public override Fill Foreground { - get { return base.Foreground; } - set { base.Foreground = value; } - } - protected override void onDraw (Context gr) { base.onDraw (gr); diff --git a/src/GraphicObjects/Scroller.cs b/src/GraphicObjects/Scroller.cs index 3eaff5f4..c248595d 100644 --- a/src/GraphicObjects/Scroller.cs +++ b/src/GraphicObjects/Scroller.cs @@ -148,7 +148,7 @@ namespace Crow 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; @@ -164,7 +164,7 @@ namespace Crow if (g != null) g.ChildrenCleared += onChildListCleared; } - return base.SetChild (_child); + base.SetChild (_child); } #endregion diff --git a/src/GraphicObjects/TabView.cs b/src/GraphicObjects/TabView.cs index d616ffc6..015f5f4f 100644 --- a/src/GraphicObjects/TabView.cs +++ b/src/GraphicObjects/TabView.cs @@ -100,7 +100,7 @@ namespace Crow set { } } - public override T AddChild<T> (T child) + public override void AddChild (GraphicObject child) { TabItem ti = child as TabItem; if (ti == null) @@ -113,7 +113,7 @@ namespace Crow SelectedTab = 0; } - return base.AddChild (child); + base.AddChild (child); } public override void RemoveChild (GraphicObject child) { diff --git a/src/GraphicObjects/TemplatedControl.cs b/src/GraphicObjects/TemplatedControl.cs index b325a0d2..422a45ec 100644 --- a/src/GraphicObjects/TemplatedControl.cs +++ b/src/GraphicObjects/TemplatedControl.cs @@ -65,8 +65,8 @@ namespace Crow string _template; string _itemTemplate; - public Dictionary<string, ItemTemplate> ItemTemplates; - + public Dictionary<string, ItemTemplate> ItemTemplates = new Dictionary<string, Crow.ItemTemplate>();//TODO: dont instantiate if not used + //but then i should test if null in msil gen [XmlAttributeAttribute][DefaultValue(null)] public string Template { get { return _template; } @@ -84,7 +84,7 @@ namespace Crow [XmlAttributeAttribute][DefaultValue("#Crow.Templates.ItemTemplate.goml")] public string ItemTemplate { get { return _itemTemplate; } - set { + set { if (value == _itemTemplate) return; @@ -146,7 +146,7 @@ namespace Crow xr.Read (); //read first child xr.Read (); //skip root node - while (!xr.EOF) { + while (!xr.EOF) { if (!xr.IsStartElement ()) { xr.Read (); continue; @@ -164,10 +164,13 @@ namespace Crow if (ItemTemplates == null) ItemTemplates = new Dictionary<string, ItemTemplate> (); - //TODO:check encoding - ItemTemplates[dataType] = new ItemTemplate (Encoding.UTF8.GetBytes(itemTmp)); + + using (IMLReader iTmp = new IMLReader (null, itemTmp)) { + ItemTemplates [dataType] = + new ItemTemplate (iTmp.RootType, iTmp.GetLoader (), dataType, datas); + } if (!string.IsNullOrEmpty (datas)) - ItemTemplates [dataType].CreateExpandDelegate(this, dataType, datas); + ItemTemplates [dataType].CreateExpandDelegate(this); continue; } @@ -197,7 +200,7 @@ namespace Crow //if no template found, load default one if (this.child == null) loadTemplate (); - + //normal xml read using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { xr.Read (); diff --git a/src/GraphicObjects/TextBox.cs b/src/GraphicObjects/TextBox.cs index 5c3772b7..81fce3e2 100644 --- a/src/GraphicObjects/TextBox.cs +++ b/src/GraphicObjects/TextBox.cs @@ -29,14 +29,13 @@ namespace Crow public class TextBox : Label { #region CTOR + public TextBox() + { } public TextBox(string _initialValue) : base(_initialValue) { } - - public TextBox() - { } #endregion #region GraphicObject overrides diff --git a/src/IMLReader.cs b/src/IMLReader.cs new file mode 100644 index 00000000..f8fd34ed --- /dev/null +++ b/src/IMLReader.cs @@ -0,0 +1,336 @@ +// +// 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; +using System.Linq; +using System.Collections.Generic; + +namespace Crow +{ + public class IMLReader : XmlTextReader + { + Interface.LoaderInvoker loader = null; + + string ImlPath; + Stream ImlStream; + + DynamicMethod dm = null; + + public ILGenerator il = null; + public Type RootType = null; + + /// <summary> + /// Finalize instatiator MSIL and return LoaderInvoker delegate + /// </summary> + public Interface.LoaderInvoker GetLoader(){ + if (loader != null) + return loader; + + il.Emit(OpCodes.Ret); + loader = (Interface.LoaderInvoker)dm.CreateDelegate (typeof(Interface.LoaderInvoker)); + return loader; + } + + #region CTOR + public IMLReader (string path) + : this(Interface.GetStreamFromPath (path)){ + ImlPath = path; + } + public IMLReader (Stream stream) + : base(stream) + { + ImlStream = stream; + createInstantiator (); + } + /// <summary> + /// Used to parse xmlFrament with same code generator linked + /// If ilGen=null, a new Code Generator will be created. + /// </summary> + public IMLReader (ILGenerator ilGen, string xmlFragment) + : base(xmlFragment, XmlNodeType.Element,null){ + il = ilGen; + + if (il != null) + return; + + createInstantiator(); + } + #endregion + + void createInstantiator(){ + readRootType(); + InitEmitter(); + emitLoader(RootType); + Read();//close tag + } + /// <summary> + /// Inits il generator, RootType must have been read first + /// </summary> + 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); + } + void emitLoader(Type crowType){ + string tmpXml = ReadOuterXml (); + + 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 (IMLReader reader = new IMLReader (il, tmpXml)) { + + string templatePath = reader.GetAttribute ("Template"); + //string itemTemplatePath = reader.GetAttribute ("ItemTemplate"); + + List<string[]> itemTemplateIds = new List<string[]> (); + bool inlineTemplate = false; + reader.Read (); + int depth = reader.Depth + 1; + while (reader.Read ()) { + if (!reader.IsStartElement () || reader.Depth > depth) + continue; + if (reader.Name == "Template") { + inlineTemplate = true; + reader.Read (); + + readChildren (reader, crowType,true); + } else if (reader.Name == "ItemTemplate") { + string dataType = "default", datas = "", path = ""; + while (reader.MoveToNextAttribute ()) { + if (reader.Name == "DataType") + dataType = reader.Value; + else if (reader.Name == "Data") + datas = reader.Value; + else if (reader.Name == "Path") + path = reader.Value; + } + reader.MoveToElement (); + using (IMLReader iTmp = new IMLReader (null, reader.ReadInnerXml ())) { + string uid = Guid.NewGuid ().ToString (); + Interface.Instantiators [uid] = + new ItemTemplate (iTmp.RootType, iTmp.GetLoader (), dataType, datas); + + itemTemplateIds.Add (new string[] { dataType, uid, datas }); + } + } + } + + if (!inlineTemplate) { + if (string.IsNullOrEmpty (templatePath)) { + DefaultTemplate dt = (DefaultTemplate)crowType.GetCustomAttributes (typeof(DefaultTemplate), true).FirstOrDefault (); + if (dt!=null) + templatePath = dt.Path; + } + + if (!string.IsNullOrEmpty (templatePath)) { + reader.il.Emit (OpCodes.Ldloc_0);//Load this templateControl ref + + reader.il.Emit (OpCodes.Ldstr, templatePath); //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 + crowType.GetMethod ("loadTemplate", BindingFlags.Instance | BindingFlags.NonPublic)); + } + } + foreach (string[] iTempId in itemTemplateIds) { + reader.il.Emit (OpCodes.Ldloc_0);//load TempControl ref + reader.il.Emit (OpCodes.Ldfld,//load ItemTemplates dic field + typeof(TemplatedControl).GetField("ItemTemplates")); + reader.il.Emit (OpCodes.Ldstr, iTempId[0]);//load key + reader.il.Emit (OpCodes.Ldstr, iTempId[1]);//load value + reader.il.Emit (OpCodes.Callvirt, + typeof(Interface).GetMethod ("GetItemTemplate")); + reader.il.Emit (OpCodes.Callvirt, + typeof(Dictionary<string, ItemTemplate>).GetMethod ("set_Item", + new Type[] { typeof(string), typeof(ItemTemplate) })); + + if (!string.IsNullOrEmpty (iTempId [2])) { + //expand delegate creation + reader.il.Emit (OpCodes.Ldloc_0);//load TempControl ref + reader.il.Emit (OpCodes.Ldfld,//load ItemTemplates dic field + typeof(TemplatedControl).GetField ("ItemTemplates")); + reader.il.Emit (OpCodes.Ldstr, iTempId [0]);//load key + reader.il.Emit (OpCodes.Callvirt, + typeof(Dictionary<string, ItemTemplate>).GetMethod ("get_Item", + new Type[] { typeof(string) })); + reader.il.Emit (OpCodes.Ldloc_0);//load root of treeView + reader.il.Emit (OpCodes.Callvirt, + typeof(ItemTemplate).GetMethod ("CreateExpandDelegate")); + } + } + } + } + + using (IMLReader reader = new IMLReader(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); + } + } + reader.il.Emit (OpCodes.Ldloc_0); + reader.il.Emit (OpCodes.Callvirt, typeof(GraphicObject).GetMethod ("loadDefaultValues")); + + if (reader.HasAttributes) { + + MethodInfo miAddBinding = typeof(GraphicObject).GetMethod ("BindMember"); + + while (reader.MoveToNextAttribute ()) { + if (reader.Name == "Style") + continue; + + MemberInfo mi = crowType.GetMember (reader.Name).FirstOrDefault(); + if (mi == null) + throw new Exception ("Member '" + reader.Name + "' not found in " + crowType.Name); + if (mi.MemberType == MemberTypes.Event) { + CompilerServices.emitBindingCreation (reader.il, reader.Name, reader.Value); + continue; + } + PropertyInfo pi = mi as PropertyInfo; + if (pi == null) + throw new Exception ("Member '" + reader.Name + "' not found in " + crowType.Name); + + if (reader.Value.StartsWith ("{")) { + CompilerServices.emitBindingCreation (reader.il, reader.Name, reader.Value.Substring (1, reader.Value.Length - 2)); + }else + 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); + } + il.Emit (OpCodes.Pop);//pop saved ref to current object + } + /// <summary> + /// Parse child node an generate corresponding msil + /// </summary> + void readChildren(IMLReader reader, Type crowType, bool templateLoading = false){ + MethodInfo miAddChild = null; + bool endTagReached = false; + while (reader.Read()){ + switch (reader.NodeType) { + case XmlNodeType.EndElement: + endTagReached = true; + break; + case XmlNodeType.Element: + //Templates + if (reader.Name == "Template" || + reader.Name == "ItemTemplate") { + reader.Skip (); + continue; + } + + 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(TemplatedContainer).IsAssignableFrom (crowType)&&!templateLoading) + miAddChild = typeof(TemplatedContainer).GetProperty("Content").GetSetMethod(); + else if (typeof(TemplatedControl).IsAssignableFrom (crowType)) + miAddChild = typeof(TemplatedControl).GetMethod ("loadTemplate", + BindingFlags.Instance | BindingFlags.NonPublic); + 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]);//TODO:search parameterless ctor + reader.il.Emit (OpCodes.Stloc_0);//child is now loc_0 + + reader.emitLoader(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; + } + } + /// <summary> + /// read first node to set GraphicObject class for loading + /// and let reader position on that node + /// </summary> + 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; + } + } +} + diff --git a/src/Instantiator.cs b/src/Instantiator.cs new file mode 100644 index 00000000..e79988fb --- /dev/null +++ b/src/Instantiator.cs @@ -0,0 +1,104 @@ +// +// 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; +using System.Threading; +using System.IO; +using System.Text; + +namespace Crow +{ + public class Instantiator + { + public Type RootType; + Interface.LoaderInvoker loader; + string imlPath; + + + #region CTOR + public Instantiator (string path){ + imlPath = path; + + #if DEBUG_LOAD + Stopwatch loadingTime = new Stopwatch (); + loadingTime.Start (); + #endif + try { + using (IMLReader itr = new IMLReader (path)){ + loader = itr.GetLoader (); + RootType = itr.RootType; + } + } catch (Exception ex) { + throw new Exception ("Error loading <" + path + ">:\n", ex); + } + + #if DEBUG_LOAD + loadingTime.Stop (); + Debug.WriteLine ("IML Instantiator creation '{2}' : {0} ticks, {1} ms", + loadingTime.ElapsedTicks, loadingTime.ElapsedMilliseconds, path); + #endif + } + public static Instantiator CreateFromImlFragment(string fragment){ + try { + using (Stream s = new MemoryStream(Encoding.UTF8.GetBytes(fragment))){ + return new Instantiator(s); + } + } catch (Exception ex) { + throw new Exception ("Error loading fragment:\n" + fragment + "\n", ex); + } + } + public Instantiator (Stream stream){ + #if DEBUG_LOAD + Stopwatch loadingTime = new Stopwatch (); + loadingTime.Start (); + #endif + using (IMLReader itr = new IMLReader (stream)){ + loader = itr.GetLoader (); + RootType = itr.RootType; + } + #if DEBUG_LOAD + loadingTime.Stop (); + Debug.WriteLine ("IML Instantiator creation '{2}' : {0} ticks, {1} ms", + loadingTime.ElapsedTicks, loadingTime.ElapsedMilliseconds, path); + #endif + } + public Instantiator (Type _root, Interface.LoaderInvoker _loader) + { + RootType = _root; + loader = _loader; + } + #endregion + + public GraphicObject CreateInstance(){ + GraphicObject tmp = (GraphicObject)Activator.CreateInstance(RootType); + loader (tmp); + return tmp; + } + public string GetImlSourcesCode(){ + try { + using (StreamReader sr = new StreamReader (imlPath)) + return sr.ReadToEnd(); + } catch (Exception ex) { + throw new Exception ("Error getting sources for <" + imlPath + ">:", ex); + } + } + } +} + diff --git a/src/Interface.cs b/src/Interface.cs index 7b324de7..ba9769b1 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -28,6 +28,7 @@ using System.Threading; using System.Xml; using System.Xml.Serialization; using Cairo; +using System.Globalization; namespace Crow { @@ -55,6 +56,7 @@ namespace Crow } public Interface(){ Interface.CurrentInterface = this; + CultureInfo.DefaultThreadCurrentCulture = System.Globalization.CultureInfo.InvariantCulture; } #endregion @@ -82,7 +84,7 @@ namespace Crow public static FontOptions FontRenderingOptions; #endregion - internal bool XmlLoading = false; + internal bool XmlLoading = true; public Dictionary<string,object> Ressources = new Dictionary<string, object>(); public Queue<LayoutingQueueItem> LayoutingQueue = new Queue<LayoutingQueueItem> (); @@ -107,14 +109,16 @@ namespace Crow 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() { @@ -176,36 +180,6 @@ namespace Crow 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) { @@ -223,52 +197,27 @@ namespace Crow System.Globalization.CultureInfo savedCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; - GraphicObject tmp = null; try { - using (Stream stream = GetStreamFromPath (path)) { - tmp = Load(stream, GetTopContainerOfXMLStream(stream)); - } + return GetInstantiator (path).CreateInstance (); } catch (Exception ex) { throw new Exception ("Error loading <" + path + ">:", ex); } Thread.CurrentThread.CurrentCulture = savedCulture; - - return tmp; } - internal static GraphicObject Load (Stream stream, Type type) - { - #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; - - #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()); - #endif - - return result; + /// <summary> + /// fetch it from cache or create it + /// </summary> + public static Instantiator GetInstantiator(string path){ + if (!Instantiators.ContainsKey(path)) + Instantiators [path] = new Instantiator(path); + return Instantiators [path]; + } + public static ItemTemplate GetItemTemplate(string path){ + if (!Instantiators.ContainsKey(path)) + Instantiators [path] = new ItemTemplate(path); + return Instantiators [path] as ItemTemplate; } - public GraphicObject LoadInterface (string path) { lock (UpdateMutex) { diff --git a/src/IMLStream.cs b/src/ItemTemplate.cs index 542797a1..1afefe2b 100644 --- a/src/IMLStream.cs +++ b/src/ItemTemplate.cs @@ -23,56 +23,31 @@ using System.IO; 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 { - public class IMLStream : MemoryStream { - public string Path; - public Type RootType; - public IMLStream(string path) : base (){ - Path = path; - using (Stream stream = Interface.GetStreamFromPath (path)) - stream.CopyTo (this); - RootType = Interface.GetTopContainerOfXMLStream (this); - } - public IMLStream(Byte[] b) : base (b){ - RootType = Interface.GetTopContainerOfXMLStream (this); - } - /// <summary> - /// Create a graphicObject instance from the this XML stream. - /// </summary> - public GraphicObject Instance { - get { - System.Globalization.CultureInfo savedCulture = Thread.CurrentThread.CurrentCulture; - Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; - - Seek (0, SeekOrigin.Begin); - GraphicObject tmp = Interface.Load (this, this.RootType); + public class ItemTemplate : Instantiator { + public EventHandler Expand; + string strDataType; + string fetchMethodName; - Thread.CurrentThread.CurrentCulture = savedCulture; - return tmp; - } + #region CTOR + public ItemTemplate(string path) + : base(path) { } - /// <summary> - /// Gets the xml source code as a string - /// </summary> - public string Source { - get { - Seek (0, SeekOrigin.Begin); - using (StreamReader sr = new StreamReader(this)) - return sr.ReadToEnd(); - } + public ItemTemplate (Type _root, Interface.LoaderInvoker _loader,string _dataType, string _fetchDataMethod) + :base(_root, _loader) + { + strDataType = _dataType; + fetchMethodName = _fetchDataMethod; } - } - public class ItemTemplate : IMLStream { - public EventHandler Expand; - - public ItemTemplate(string path) - : base(path){} - public ItemTemplate(Byte[] b) - : base(b){} + #endregion - public void CreateExpandDelegate (TemplatedControl host, string strDataType, string method){ + public void CreateExpandDelegate (TemplatedControl host){ Type dataType = Type.GetType(strDataType); Type hostType = typeof(TemplatedControl);//not sure is the best place to put the dyn method Type evtType = typeof(EventHandler); @@ -83,7 +58,7 @@ namespace Crow Type handlerArgsType = evtParams [1].ParameterType; Type [] args = { typeof (object), typeof (object), handlerArgsType }; - DynamicMethod dm = new DynamicMethod ("dyn_expand_" + method, + DynamicMethod dm = new DynamicMethod ("dyn_expand_" + fetchMethodName, typeof (void), args, hostType); @@ -110,7 +85,7 @@ namespace Crow il.Emit (OpCodes.Ldarg_1); il.Emit (OpCodes.Callvirt, typeof(GraphicObject).GetProperty("DataSource").GetGetMethod ()); - MethodInfo miGetDatas = dataType.GetMethod (method, new Type[] {}); + MethodInfo miGetDatas = dataType.GetMethod (fetchMethodName, new Type[] {}); il.Emit (OpCodes.Callvirt, miGetDatas); il.Emit (OpCodes.Callvirt, listBoxType.GetProperty("Data").GetSetMethod ()); diff --git a/src/LayoutingQueueItem.cs b/src/LayoutingQueueItem.cs index b2a5f3ca..a7909022 100644 --- a/src/LayoutingQueueItem.cs +++ b/src/LayoutingQueueItem.cs @@ -107,10 +107,10 @@ namespace Crow Layoutable.RegisteredLayoutings |= LayoutType; Interface.CurrentInterface.DiscardQueue.Enqueue (this); } - //#if DEBUG_LAYOUTING + #if DEBUG_LAYOUTING else Debug.WriteLine ("\tDELETED => " + this.ToString ()); - //#endif + #endif } #if DEBUG_LAYOUTING currentLQI = null; |