From: Jean-Philippe Bruyère Date: Mon, 13 Sep 2021 10:12:01 +0000 (+0000) Subject: In Style TG.ItemTemplate handling, removed IFace DefaultTemplates and handle them... X-Git-Tag: v0.9.7-beta~16 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=b4fe07b2b51045eff251a96b442219cbb68aae6f;p=jp%2Fcrow.git In Style TG.ItemTemplate handling, removed IFace DefaultTemplates and handle them along with normal iTors --- diff --git a/Crow/src/DebugUtils/DbgEvtType.cs b/Crow/src/DebugUtils/DbgEvtType.cs index 89e86076..4acd1d27 100644 --- a/Crow/src/DebugUtils/DbgEvtType.cs +++ b/Crow/src/DebugUtils/DbgEvtType.cs @@ -73,7 +73,7 @@ namespace Crow GODraw = Widget | Drawing | 0x01, GORecreateCache = Widget | Drawing | 0x02, GOUpdateCache = Widget | Drawing | 0x03, - GOPaintCache = Widget | Drawing | 0x04, + GOPaintCache = Widget | Drawing | 0x04, GOPaint = Widget | Drawing | 0x05, GOCreateSurface = Widget | Drawing | 0x06, GOCreateContext = Widget | Drawing | 0x07, diff --git a/Crow/src/DebugUtils/DebugLogger.cs b/Crow/src/DebugUtils/DebugLogger.cs index 07313382..b84077a6 100644 --- a/Crow/src/DebugUtils/DebugLogger.cs +++ b/Crow/src/DebugUtils/DebugLogger.cs @@ -13,7 +13,7 @@ using System.Threading; using Crow.DebugLogger; namespace Crow -{ +{ public static class DbgLogger { public static DbgEvtType IncludeEvents = DbgEvtType.All; @@ -26,7 +26,7 @@ namespace Crow //=> IncludeEvents != DbgEvtType.None && (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) == IncludeEvents; //=> IncludeEvents != DbgEvtType.None && (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) == IncludeEvents; => IncludeEvents == DbgEvtType.All || (IncludeEvents != DbgEvtType.None && (evtType & IncludeEvents) != 0); - + static object logMutex = new object (); @@ -41,7 +41,7 @@ namespace Crow if (startedEvents [Thread.CurrentThread.ManagedThreadId].Count == 0) return events; DbgEvent e = startedEvents [Thread.CurrentThread.ManagedThreadId].Peek (); - if (e.Events == null) + if (e.Events == null) e.Events = new List (); return e.Events; } @@ -65,7 +65,7 @@ namespace Crow if (!startedEvents.ContainsKey (Thread.CurrentThread.ManagedThreadId)) startedEvents [Thread.CurrentThread.ManagedThreadId] = new Stack (); startedEvents [Thread.CurrentThread.ManagedThreadId].Push (evt); - chrono.Start (); + chrono.Start (); } #endif } @@ -90,7 +90,7 @@ lock (logMutex) { [Conditional ("DEBUG_LOG")] public static void EndEvent (DbgEvtType evtType, bool discardIfNoChildEvents = false) { -#if DEBUG_LOG +#if DEBUG_LOG if (!logevt (evtType)) return; @@ -113,7 +113,7 @@ lock (logMutex) { // End layouting queue event and set the corresponding lqi [Conditional ("DEBUG_LOG")] public static void EndEvent (DbgEvtType evtType, LayoutingQueueItem lqi) { -#if DEBUG_LOG +#if DEBUG_LOG if (!logevt (evtType)) return; @@ -155,7 +155,7 @@ lock (logMutex) { [Conditional("DEBUG_LOG")] public static void AddEvent (DbgEvtType evtType, params object [] data) { -#if DEBUG_LOG +#if DEBUG_LOG if (!logevt (evtType)) return; @@ -168,7 +168,7 @@ lock (logMutex) { } [Conditional("DEBUG_LOG")] public static void AddEventWithMsg (DbgEvtType evtType, string message, params object [] data) { -#if DEBUG_LOG +#if DEBUG_LOG if (!logevt (evtType)) return; @@ -197,7 +197,7 @@ lock (logMutex) { else evt.Message = $"{data[1]}"; } - + } else if (data [0] is LayoutingQueueItem lqi) evt = new DbgLayoutEvent (chrono.ElapsedTicks, evtType, (lqi.Layoutable as Widget).instanceIndex, lqi.LayoutType, lqi.result, lqi.Slot, lqi.NewSlot); else @@ -206,8 +206,8 @@ lock (logMutex) { if (ConsoleOutput) { if (evt.type.HasFlag (DbgEvtType.Error)) { Console.ForegroundColor = ConsoleColor.Red; - } - if (evt is DbgWidgetEvent we) + } + if (evt is DbgWidgetEvent we) Console.WriteLine ($"{evt.Print()} {Widget.GraphicObjects[we.InstanceIndex]}"); else Console.WriteLine ($"{evt.Print()}"); @@ -225,10 +225,10 @@ lock (logMutex) { go.xLevel = xLevel; if (go is Group gr) { - for (int i = 0; i < gr.Children.Count; i++) + for (int i = 0; i < gr.Children.Count; i++) parseTree (gr.Children[i], xLevel + 1, i); } else if (go is PrivateContainer pc) - parseTree (pc.getTemplateRoot, xLevel + 1); + parseTree (pc.getTemplateRoot, xLevel + 1); } static void saveEventList (StreamWriter s, List evts, int level = 0) { @@ -270,7 +270,7 @@ lock (logMutex) { #endif } [Conditional("DEBUG_LOG")] - public static void Save(Interface iface, Stream stream, int startingWidgetsIndex = -1, bool saveEvents = true) { + public static void Save(Interface iface, Stream stream, int startingWidgetsIndex = -1, bool saveEvents = true) { #if DEBUG_LOG using (StreamWriter writer = new StreamWriter (stream, Encoding.UTF8, 1024, true)) { lock (logMutex) @@ -290,7 +290,7 @@ lock (logMutex) { } if (saveEvents) { - if (startingWidgetsIndex >= 0) + if (startingWidgetsIndex >= 0) writer.WriteLine ("[Events]"); saveEventList (writer, events); startedEvents.Clear (); @@ -306,12 +306,12 @@ lock (logMutex) { if (!File.Exists (logFile)) return; using (Stream stream = new FileStream (logFile, FileMode.Open, FileAccess.Read)) - Load (stream, events, widgets); + Load (stream, events, widgets); } public static void Load (Stream stream, List events, List widgets) - { + { using (StreamReader reader = new StreamReader (stream)) { - + if (widgets != null) { if (events != null && reader.ReadLine () != "[GraphicObjects]") return; @@ -336,7 +336,7 @@ lock (logMutex) { reader.Read (); level++; } - DbgEvent evt = DbgEvent.Parse (reader.ReadLine ()); + DbgEvent evt = DbgEvent.Parse (reader.ReadLine ()); if (level == 0) { startedEvents.Clear (); events.Add (evt); diff --git a/Crow/src/IML/CompilerServices.cs b/Crow/src/IML/CompilerServices.cs index 4ad57009..3daf82ab 100644 --- a/Crow/src/IML/CompilerServices.cs +++ b/Crow/src/IML/CompilerServices.cs @@ -82,10 +82,13 @@ namespace Crow.IML internal static MethodInfo miAddITemp = typeof(Dictionary).GetMethod ("set_Item", new Type[] { typeof(string), typeof(ItemTemplate) }); internal static MethodInfo miGetITempFromDic = typeof(Dictionary).GetMethod ("get_Item", new Type[] { typeof(string) }); internal static FieldInfo fldItemTemplates = typeof(TemplatedGroup).GetField("ItemTemplates"); + internal static MethodInfo miGet_TG_HasItemTemplates = typeof(TemplatedGroup).GetProperty ("HasItemTemplates").GetGetMethod (); + internal static PropertyInfo piItemTemplate = typeof(TemplatedGroup).GetProperty("ItemTemplate"); + internal static PropertyInfo piTemplate = typeof(TemplatedControl).GetProperty("Template"); internal static MethodInfo miLoadPage = typeof(TemplatedGroup).GetMethod ("loadPage", BindingFlags.Instance | BindingFlags.NonPublic| BindingFlags.Public); internal static MethodInfo miRegisterSubData = typeof(TemplatedGroup).GetMethod ("registerSubData", BindingFlags.Instance | BindingFlags.NonPublic); internal static MethodInfo miIsAlreadyExpanded = typeof(TemplatedGroup).GetMethod("emitHelperIsAlreadyExpanded", BindingFlags.Instance | BindingFlags.NonPublic); - + internal static MethodInfo miCreateExpDel = typeof(ItemTemplate).GetMethod ("CreateExpandDelegate"); internal static FieldInfo fiFetchMethodName = typeof(ItemTemplate).GetField("fetchMethodName", BindingFlags.Instance | BindingFlags.NonPublic); @@ -218,7 +221,7 @@ namespace Crow.IML il.Emit(OpCodes.Ldtoken, pi.PropertyType); il.Emit(OpCodes.Call, CompilerServices.miGetTypeFromHandle); //load enum value name - il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:implement here string format? + il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:implement here string format? il.Emit (OpCodes.Call, CompilerServices.miParseEnum); if (CompilerServices.miParseEnum.ReturnType != pi.PropertyType) @@ -288,7 +291,7 @@ namespace Crow.IML #endif Type t = instance.GetType(); MethodInfo mi = t.GetMethod (method, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); - return mi ?? CompilerServices.SearchExtMethod (t, method); + return mi ?? CompilerServices.SearchExtMethod (t, method); } /// /// set value, convert if required @@ -373,7 +376,7 @@ namespace Crow.IML if (dstType == typeof(string) || dstType == typeof (object))//TODO:object should be allowed to return null and not "" return ""; if (dstType.IsValueType) - return Activator.CreateInstance (dstType); + return Activator.CreateInstance (dstType); } catch (Exception ex) { Console.WriteLine (ex.ToString ()); return ""; @@ -412,10 +415,10 @@ namespace Crow.IML { foundMI = null; if (assembly == null) - return false; + return false; foreach (Type t in assembly.GetExportedTypes().Where (ty => ty.IsDefined (typeof (ExtensionAttribute), false))) { - foreach (MethodInfo mi in t.GetMethods + foreach (MethodInfo mi in t.GetMethods (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Where (m=> m.Name == methodName && m.IsDefined (typeof (ExtensionAttribute), false) && m.GetParameters ().Length > 0)) { @@ -426,10 +429,10 @@ namespace Crow.IML return true; } curType = curType.BaseType; - } + } } - - } + + } return false; } /// @@ -869,7 +872,7 @@ namespace Crow.IML knownTypes.Add (strDataType, dataType); return dataType; } - foreach (Assembly a in Interface.crowAssemblies) { + foreach (Assembly a in Interface.crowAssemblies) { foreach (Type expT in a.GetExportedTypes ()) { if (expT.Name != strDataType && expT.FullName != strDataType) continue; @@ -1020,7 +1023,7 @@ namespace Crow.IML { return EnumsNET.FlagEnums.IsFlagEnum (enumType) ? EnumsNET.FlagEnums.ParseFlags (enumType, val, true, "|") : - EnumsNET.Enums.Parse (enumType, val, true); + EnumsNET.Enums.Parse (enumType, val, true); } catch (System.Exception) { diff --git a/Crow/src/IML/Instantiator.cs b/Crow/src/IML/Instantiator.cs index 087d4f97..07ebfd3c 100644 --- a/Crow/src/IML/Instantiator.cs +++ b/Crow/src/IML/Instantiator.cs @@ -246,7 +246,7 @@ namespace Crow.IML { /// the string triplet dataType, itemTmpID read as attribute of this tag /// current xml text reader /// file containing the templates if its a dedicated one - string[] parseItemTemplateTag (XmlReader reader, string itemTemplatePath = "") { + static string[] parseItemTemplateTag (Interface iface, XmlReader reader, string itemTemplatePath = "") { string dataType = "default", datas = "", path = "", dataTest = "TypeOf"; while (reader.MoveToNextAttribute ()) { if (reader.Name == "DataType") @@ -263,11 +263,11 @@ namespace Crow.IML { string itemTmpID = itemTemplatePath; if (string.IsNullOrEmpty (path)) { - itemTmpID += Guid.NewGuid ().ToString (); + itemTmpID += Guid.NewGuid ().ToString ();//inline item template iface.ItemTemplates [itemTmpID] = new ItemTemplate (iface, new MemoryStream (Encoding.UTF8.GetBytes (reader.ReadInnerXml ())), dataTest, dataType, datas); - } else { + } else {//separate iml file if (!reader.IsEmptyElement) throw new Exception ("ItemTemplate with Path attribute set may not include sub nodes"); itemTmpID += $"{path}{dataType}{datas}"; @@ -308,7 +308,7 @@ namespace Crow.IML { reader.Read (); readChildren (reader, ctx, -1); } else if (reader.Name == NT_iTemp) - itemTemplateIds.Add (parseItemTemplateTag (reader)); + itemTemplateIds.Add (parseItemTemplateTag (iface, reader)); } if (!inlineTemplate) {//load from path or default template @@ -322,41 +322,17 @@ namespace Crow.IML { } } if (itemTemplateIds.Count == 0) { - //try to load ItemTemplate(s) from ItemTemplate attribute of TemplatedGroup + //try to load ItemTemplate(s) from ItemTemplate property of TemplatedGroup if (!string.IsNullOrEmpty (itemTemplatePath)) { //check if it is already loaded in cache as a single itemTemplate instantiator - if (iface.ItemTemplates.ContainsKey (itemTemplatePath)) { + if (iface.ItemTemplates.ContainsKey (itemTemplatePath)) itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "" }); - } else { - using (Stream stream = iface.GetStreamFromPath (itemTemplatePath)) { - //itemtemplate files may have multiple root nodes - XmlReaderSettings itrSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment }; - using (XmlReader itr = XmlReader.Create (stream, itrSettings)) { - while (itr.Read ()) { - if (!itr.IsStartElement ()) - continue; - if (itr.NodeType == XmlNodeType.Element) { - if (itr.Name != NT_iTemp) { - //the file contains a single template to use as default - iface.ItemTemplates [itemTemplatePath] = - new ItemTemplate (iface, itr); - itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "", "TypeOf" }); - break;//we should be at the end of the file - } - itemTemplateIds.Add (parseItemTemplateTag (itr, itemTemplatePath)); - } - } - } - } - } + else + itemTemplateIds.AddRange (loadItemTemplatesFromTemplatedGroupProperty (iface, itemTemplatePath)); } } if (!ctx.nodesStack.Peek ().IsTemplatedGroup) return; - //add the default item template if no default is defined - if (!itemTemplateIds.Any(ids=>ids[0] == "default")) - itemTemplateIds.Add (new string [] { "default", "#Crow.DefaultItem.template", "", "TypeOf"}); - //get item templates foreach (string [] iTempId in itemTemplateIds) { ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref ctx.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates);//load ItemTemplates dic field @@ -375,13 +351,33 @@ namespace Crow.IML { ctx.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates); ctx.il.Emit (OpCodes.Ldstr, iTempId [0]);//load key ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miGetITempFromDic); - ctx.il.Emit (OpCodes.Ldloc_0);//load root of treeView + ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miCreateExpDel); } } } } - + public static IEnumerable loadItemTemplatesFromTemplatedGroupProperty (Interface iface, string itemTemplatePath) { + using (Stream stream = iface.GetStreamFromPath (itemTemplatePath)) { + //itemtemplate files may have multiple root nodes + XmlReaderSettings itrSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment }; + using (XmlReader itr = XmlReader.Create (stream, itrSettings)) { + while (itr.Read ()) { + if (!itr.IsStartElement ()) + continue; + if (itr.NodeType == XmlNodeType.Element) { + if (itr.Name != NT_iTemp) { + //the file contains a single template to use as default + iface.ItemTemplates [itemTemplatePath] = new ItemTemplate (iface, itr); + yield return new string [] { "default", itemTemplatePath, "", "TypeOf" }; + break;//we should be at the end of the file + } + yield return parseItemTemplateTag (iface, itr, itemTemplatePath); + } + } + } + } + } #if DESIGN_MODE void emitSetDesignAttribute (IMLContext ctx, string name, string value){ //store member value in iml diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index 7bf8cb39..b8e52a56 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -652,10 +652,6 @@ namespace Crow /// public Dictionary Instantiators; /// - /// default templates dic by metadata token - /// - public Dictionary DefaultTemplates; - /// /// Item templates stored with their index /// public Dictionary ItemTemplates; @@ -779,7 +775,6 @@ namespace Crow Styling = new Dictionary (initCapacity); DefaultValuesLoader = new Dictionary (initCapacity); Instantiators = new Dictionary (initCapacity); - DefaultTemplates = new Dictionary (initCapacity); ItemTemplates = new Dictionary (initCapacity); } void loadThemeFiles () { @@ -799,15 +794,6 @@ namespace Crow } } } - if (Directory.Exists (path)) { - path = Path.Combine (Theme, "DefaultTemplates"); - foreach (string iml in Directory.GetFiles (path, "*.*", SearchOption.AllDirectories)) { - string resId = $"#{iml.Substring (path.Length + 1).Replace (Path.DirectorySeparatorChar, '.')}"; - //int mdTok = Instantiator.tryGetGOType (resId.Substring (6, resId.Length - 15)).MetadataToken; - using (Stream s = new FileStream (iml, FileMode.Open, FileAccess.Read)) - DefaultTemplates[resId] = new IML.Instantiator (this, s, resId); - } - } path = Path.Combine (Theme, "IML"); if (Directory.Exists (path)) { foreach (string iml in Directory.GetFiles (path, "*.*", SearchOption.AllDirectories)) { diff --git a/Crow/src/Widgets/TemplatedControl.cs b/Crow/src/Widgets/TemplatedControl.cs index a50352ee..909c4bb8 100644 --- a/Crow/src/Widgets/TemplatedControl.cs +++ b/Crow/src/Widgets/TemplatedControl.cs @@ -41,6 +41,10 @@ namespace Crow /// /// Template path /// + /// + /// The 'null' default value with the 'NOT_SET' field init value force a loading + /// of the default template by passing the first equality check. + /// //TODO: this property should be renamed 'TemplatePath' [DefaultValue(null)] public string Template { @@ -119,15 +123,12 @@ namespace Crow this.ClearTemplateBinding(); if (template == null) { - string defTmpId = this.GetType ().FullName + ".template"; - if (!IFace.DefaultTemplates.ContainsKey (defTmpId)) { - - Stream s = IFace.GetStreamFromPath ("#" + defTmpId); - if (s == null) - throw new Exception (string.Format ("No default template found for '{0}'", this.GetType ().FullName)); - IFace.DefaultTemplates [defTmpId] = new IML.Instantiator (IFace, s, defTmpId); + try { + string defTmpId = $"#{this.GetType ().FullName}.template"; + this.SetChild (IFace.GetInstantiator (defTmpId).CreateInstance()); + } catch (Exception ex) { + throw new Exception ($"Default template loading error for '{this.GetType ().FullName}'", ex); } - this.SetChild (IFace.DefaultTemplates[defTmpId].CreateInstance()); }else this.SetChild (template); } diff --git a/Crow/src/Widgets/TemplatedGroup.cs b/Crow/src/Widgets/TemplatedGroup.cs index 9ec8cb5e..ce50bbe2 100644 --- a/Crow/src/Widgets/TemplatedGroup.cs +++ b/Crow/src/Widgets/TemplatedGroup.cs @@ -76,6 +76,10 @@ namespace Crow { //TODO: dont instantiate ItemTemplates if not used //but then i should test if null in msil gen public Dictionary ItemTemplates = new Dictionary(); + /// + /// True if this templated group contains at least one item template. + /// + public bool HasItemTemplates => ItemTemplates.Count > 0; /// /// Keep track of expanded subnodes and closed time to unload @@ -99,6 +103,23 @@ namespace Crow { //TODO:reload list with new template? NotifyValueChangedAuto (_itemTemplate); + + loadItemTemplateFromPropertyValue (); + } + } + /// + /// load ItemTemplate(s) from ItemTemplate property + /// + void loadItemTemplateFromPropertyValue () { + ItemTemplates.Clear(); + if (string.IsNullOrEmpty (_itemTemplate)) + return; + foreach (string[] itempIds in Instantiator.loadItemTemplatesFromTemplatedGroupProperty (IFace, _itemTemplate)) { + ItemTemplate itemp = IFace.GetItemTemplate (itempIds[1]); + ItemTemplates.Add (itempIds[0], itemp); + if (string.IsNullOrEmpty (itempIds[2])) + continue; + itemp.CreateExpandDelegate (this); } } protected override void loadTemplate(Widget template = null) @@ -456,39 +477,57 @@ namespace Crow { } protected void loadItem(object o, Group page, string _dataTest){ - if (o == null)//TODO:surely a threading sync problem + if (o == null) {//TODO:surely a threading sync problem + DbgLogger.AddEventWithMsg (DbgEvtType.TGLoadingThread|DbgEvtType.Warning, "loadItem called with 'null' item."); return; + } Widget g = null; ItemTemplate iTemp = null; Type dataType = o.GetType (); + + //First, a template for this item has to be choosen. + + //By default, the item template selection is done on the full type name of the item. + //This is controled by the 'DataTest' attribute of the 'ItemTemplate' IML element. + //Its default value is 'TypeOf'. string itempKey = dataType.FullName; + //If 'DataTest' is not 'TypeOf', the item template selection will be done on the value of + //a member of the item which name is given in the 'DataTest' attribute. //if item template selection is not done depending on the type of item - //dataTest must contains a member name of the item + //dataTest must contains a member name of the item to test for. if (_dataTest != "TypeOf") { try { itempKey = CompilerServices.getValue (dataType, o, _dataTest)?.ToString (); } catch { - itempKey = dataType.FullName; + DbgLogger.AddEventWithMsg (DbgEvtType.TGLoadingThread|DbgEvtType.Warning, "dataTest fallback to full type name."); + itempKey = dataType.FullName;//fallback to full type name } } - if (ItemTemplates.ContainsKey (itempKey)) iTemp = ItemTemplates [itempKey]; else { - foreach (string it in ItemTemplates.Keys) { - if (it == "default") - continue; - Type t = CompilerServices.getTypeFromName (it); - if (t == null) - continue; - if (t.IsAssignableFrom (dataType)) {//TODO:types could be cached - iTemp = ItemTemplates [it]; - break; + if (_dataTest == "Typeof") {//item template selection on full type name + //search ItemTemplates for an existing parent class + foreach (string it in ItemTemplates.Keys) { + if (it == "default") + continue; + Type t = CompilerServices.getTypeFromName (it); + if (t == null) + continue; + if (t.IsAssignableFrom (dataType)) {//TODO:types could be cached + iTemp = ItemTemplates [it]; + break; + } } } - if (iTemp == null) - iTemp = ItemTemplates ["default"]; + //if no item template is found, load the local then the global default one. + if (iTemp == null) { + if (ItemTemplates.ContainsKey ("default")) + iTemp = ItemTemplates ["default"]; + else + iTemp = IFace.GetItemTemplate ("#Crow.DefaultItem.template"); + } } if (loadingThread == null) Monitor.Enter(IFace.UpdateMutex); diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index c114fb3f..512d27e0 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -1233,22 +1233,33 @@ namespace Crow } } - //first set template if it exists - PropertyInfo piTmp = thisType.GetProperty ("Template"); - if (piTmp != null) { + //Process Template and ItemTemplate properties first + if (typeof(TemplatedControl).IsAssignableFrom (thisType)) { //if template has been declared in IML, cancel style or default loading System.Reflection.Emit.Label cancelTemplateLoad = il.DefineLabel (); il.Emit (OpCodes.Ldloc_0);//load target widget il.Emit (OpCodes.Ldfld, typeof (PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic)); il.Emit (OpCodes.Brtrue, cancelTemplateLoad); - setDefaultValue (il, piTmp, ref styling); + setDefaultValue (il, CompilerServices.piTemplate, ref styling); il.MarkLabel (cancelTemplateLoad); } + if (typeof(TemplatedGroup).IsAssignableFrom (thisType)) { + //style may contains a 'ItemTemplate' value, but if item templates have been provided in IML, + //ItemTemplate value from style is ignored. + System.Reflection.Emit.Label cancelItemTemplateLoad = il.DefineLabel (); + il.Emit (OpCodes.Ldloc_0);//load target widget + il.Emit (OpCodes.Call, CompilerServices.miGet_TG_HasItemTemplates); + il.Emit (OpCodes.Brtrue, cancelItemTemplateLoad); + + setDefaultValue (il, CompilerServices.piItemTemplate, ref styling); + + il.MarkLabel (cancelItemTemplateLoad); + } foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { - if (pi.Name == "Template") + if (pi.Name == "Template" || pi.Name == "ItemTemplate") continue; setDefaultValue (il, pi, ref styling); } diff --git a/Samples/PerfTests/Program.cs b/Samples/PerfTests/Program.cs index fabf4b45..17af6282 100644 --- a/Samples/PerfTests/Program.cs +++ b/Samples/PerfTests/Program.cs @@ -14,9 +14,9 @@ namespace PerfTests { class TestInterface : Interface { -#if NETCOREAPP +#if NETCOREAPP static IntPtr resolveUnmanaged (Assembly assembly, String libraryName) { - + switch (libraryName) { case "glfw3": @@ -24,15 +24,15 @@ namespace PerfTests case "rsvg-2.40": return NativeLibrary.Load("rsvg-2", assembly, null); } - Console.WriteLine ($"[UNRESOLVE] {assembly} {libraryName}"); + Console.WriteLine ($"[UNRESOLVE] {assembly} {libraryName}"); return IntPtr.Zero; } static TestInterface () { System.Runtime.Loader.AssemblyLoadContext.Default.ResolvingUnmanagedDll+=resolveUnmanaged; } -#endif - readonly int count = 10, updateCycles = 0; +#endif + readonly int count = 10, updateCycles = 0; readonly bool screenOutput = false; readonly string inDirectory = null;//directory to test readonly string outFilePath; @@ -129,7 +129,7 @@ namespace PerfTests screenOutput = true; break; case "--help": - default: + default: throw new Exception (); } } @@ -167,12 +167,12 @@ namespace PerfTests } else { SolidBackground = false; initBackend (true); - + CreateMainSurface (ref clientRectangle); } initDictionaries (); - loadStyling (); + loadStyling (); } protected override void Dispose (bool disposing) { @@ -212,7 +212,7 @@ namespace PerfTests public override string ToString () => $"{MinElapsed};{MaxElapsed};{MeanElapsed};{MedianElapsed};{sigmaElapsed};{MinMem};{MaxMem};{MeanMem};{MedianMem};{sigmaMem};{MinAlloc};{MaxAlloc};{MeanAlloc};{MedianAlloc};{sigmaAlloc}"; - } + } void getMemUsage (out long allocations, out long memory ) { GC.Collect (); @@ -246,13 +246,13 @@ namespace PerfTests if (StartStage == Stage.ITor) { getMemUsage (out allocBefore, out totMemBefore); - chrono.Restart (); + chrono.Restart (); } Crow.IML.Instantiator iTor = isImlFragment ? Crow.IML.Instantiator.CreateFromImlFragment (this, iml) : new Crow.IML.Instantiator (this, iml); - if (EndStage == Stage.ITor) { + if (EndStage == Stage.ITor) { chrono.Stop (); getMemUsage (out allocAfter, out totMemAfter); } else { @@ -285,7 +285,7 @@ namespace PerfTests w.DataSource = this; - if (EndStage == Stage.Datasource) { + if (EndStage == Stage.Datasource) { chrono.Stop (); getMemUsage (out allocAfter, out totMemAfter); } else { @@ -323,7 +323,7 @@ namespace PerfTests } } } - } + } DeleteWidget (w); w = null; @@ -343,7 +343,7 @@ namespace PerfTests /*this.Instantiators.Clear (); this.Templates.Clear (); this.DefaultTemplates.Clear ();*/ - this.DefaultValuesLoader.Clear (); + this.DefaultValuesLoader.Clear (); measures[i].AllocatedKB = (double)(allocAfter - allocBefore) / 1024.0; measures[i].UsedKB = (double)(totMemAfter - totMemBefore) / 1024.0; @@ -384,17 +384,17 @@ namespace PerfTests if (measures[i].Elapsed < trimMinElapsed && measures[i].Elapsed != extMinElapsed) trimMinElapsed = measures[i].Elapsed; if (measures[i].Elapsed > trimMaxElapsed && measures[i].Elapsed != extMaxElapsed) - trimMaxElapsed = measures[i].Elapsed; + trimMaxElapsed = measures[i].Elapsed; if (measures[i].UsedKB < trimMinMem && measures[i].UsedKB != extMinMem) trimMinMem = measures[i].UsedKB; if (measures[i].UsedKB > trimMaxMem && measures[i].UsedKB != extMaxMem) - trimMaxMem = measures[i].UsedKB; + trimMaxMem = measures[i].UsedKB; if (measures[i].AllocatedKB < trimMinAlloc && measures[i].AllocatedKB != extMinAlloc) trimMinAlloc = measures[i].AllocatedKB; if (measures[i].AllocatedKB > trimMaxAlloc && measures[i].AllocatedKB != extMaxAlloc) - trimMaxAlloc = measures[i].AllocatedKB; + trimMaxAlloc = measures[i].AllocatedKB; } result.MinElapsed = trimMinElapsed; @@ -425,7 +425,7 @@ namespace PerfTests result.sigmaElapsed = Math.Sqrt (result.sigmaElapsed / (count - 2)); result.sigmaMem = Math.Sqrt (result.sigmaMem / (count - 2)); - result.sigmaAlloc = Math.Sqrt (result.sigmaAlloc / (count - 2)); + result.sigmaAlloc = Math.Sqrt (result.sigmaAlloc / (count - 2)); } void testDir (string dirPath, int level = 0) { @@ -434,15 +434,15 @@ namespace PerfTests Console.WriteLine (label, -50); level++; - foreach (string d in Directory.GetDirectories (dirPath)) + foreach (string d in Directory.GetDirectories (dirPath)) testDir (d, level); foreach (string f in Directory.GetFiles (dirPath, "*.crow")) { label = $"{new string (' ', level * 4)}{ Path.GetFileName (f)}"; try { - - Test (f); - + + Test (f); + if (logToDisk) { writer.WriteLine ($"{f};{result}"); Console.Write ("."); @@ -482,7 +482,7 @@ namespace PerfTests measures = ArrayPool.Shared.Rent (count); foreach (string unitTest in unitTests) { - //for (int i = 0; i < 2; i++) { + //for (int i = 0; i < 2; i++) { Test (unitTest, true); if (logToDisk) { @@ -516,7 +516,7 @@ namespace PerfTests public static void Main (string [] args) { - + try { using (TestInterface iface = new TestInterface (args)) { if (string.IsNullOrEmpty(iface.inDirectory)) diff --git a/Samples/common/ui/Interfaces/Divers/testStacks.crow b/Samples/common/ui/Interfaces/Divers/testStacks.crow deleted file mode 100644 index 99279cd4..00000000 --- a/Samples/common/ui/Interfaces/Divers/testStacks.crow +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file