]> O.S.I.I.S - jp/crow.git/commitdiff
In Style TG.ItemTemplate handling, removed IFace DefaultTemplates and handle them...
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 13 Sep 2021 10:12:01 +0000 (10:12 +0000)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 13 Sep 2021 10:12:01 +0000 (10:12 +0000)
Crow/src/DebugUtils/DbgEvtType.cs
Crow/src/DebugUtils/DebugLogger.cs
Crow/src/IML/CompilerServices.cs
Crow/src/IML/Instantiator.cs
Crow/src/Interface.cs
Crow/src/Widgets/TemplatedControl.cs
Crow/src/Widgets/TemplatedGroup.cs
Crow/src/Widgets/Widget.cs
Samples/PerfTests/Program.cs
Samples/common/ui/Interfaces/Divers/testStacks.crow [deleted file]

index 89e860763db20f67053f775a693b202f96e3438e..4acd1d27be6a4c8efd17feca6c1baf5d504ea27f 100644 (file)
@@ -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,
index 07313382173bb07c958976e09c8ccce49dc25ff3..b84077a64b632b0a256b48da5be6bd2f7c72b262 100644 (file)
@@ -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<DbgEvent> ();
                                        return e.Events;
                                }
@@ -65,7 +65,7 @@ namespace Crow
                                if (!startedEvents.ContainsKey (Thread.CurrentThread.ManagedThreadId))
                                        startedEvents [Thread.CurrentThread.ManagedThreadId] = new Stack<DbgEvent> ();
                                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<DbgEvent> 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<DbgEvent> events, List<DbgWidgetRecord> 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);
index 4ad5700924e78a3c05cfa5c7578e1f2b19a8ae40..3daf82ab7627ac387afaf68eaa7e3f9dc3cf7bca 100644 (file)
@@ -82,10 +82,13 @@ namespace Crow.IML
                internal static MethodInfo miAddITemp = typeof(Dictionary<string, ItemTemplate>).GetMethod ("set_Item", new Type[] { typeof(string), typeof(ItemTemplate) });
                internal static MethodInfo miGetITempFromDic = typeof(Dictionary<string, ItemTemplate>).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);
                }
                /// <summary>
                /// 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;
                }
                /// <summary>
@@ -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)
                        {
index 087d4f97826046667f029ddc1575513bb047524f..07ebfd3cd5860089c0e2f5ac52715a57b747472d 100644 (file)
@@ -246,7 +246,7 @@ namespace Crow.IML {
                /// <returns>the string triplet dataType, itemTmpID read as attribute of this tag</returns>
                /// <param name="reader">current xml text reader</param>
                /// <param name="itemTemplatePath">file containing the templates if its a dedicated one</param>
-               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<string[]> 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
index 7bf8cb39216d81ddf3cd5f4314269af25d4eef43..b8e52a5634d368e37e1424c25b06841542fe0b30 100644 (file)
@@ -652,10 +652,6 @@ namespace Crow
                /// </summary>
                public Dictionary<String, Instantiator> Instantiators;
                /// <summary>
-               /// default templates dic by metadata token
-               /// </summary>
-               public Dictionary<string, Instantiator> DefaultTemplates;
-               /// <summary>
                /// Item templates stored with their index
                /// </summary>
                public Dictionary<String, ItemTemplate> ItemTemplates;
@@ -779,7 +775,6 @@ namespace Crow
                        Styling = new Dictionary<string, Style> (initCapacity);
                        DefaultValuesLoader = new Dictionary<string, LoaderInvoker> (initCapacity);
                        Instantiators = new Dictionary<string, Instantiator> (initCapacity);
-                       DefaultTemplates = new Dictionary<string, Instantiator> (initCapacity);
                        ItemTemplates = new Dictionary<string, ItemTemplate> (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)) {
index a50352ee01fac5ce18437f4979672f885d7e40be..909c4bb81e7298800a9d5849773a8dd4e20e12bb 100644 (file)
@@ -41,6 +41,10 @@ namespace Crow
                /// <summary>
                /// Template path
                /// </summary>
+               /// <remark>
+               /// The 'null' default value with the 'NOT_SET' field init value  force a loading
+               /// of the default template by passing the first equality check.
+               /// </remark>
                //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);
                }
index 9ec8cb5ef48c0998689072c9d3d39ffc0a1c1dfe..ce50bbe29c142d024226558dfc4ea312835cb308 100644 (file)
@@ -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<string, ItemTemplate> ItemTemplates = new Dictionary<string, ItemTemplate>();
+               /// <summary>
+               /// True if this templated group contains at least one item template.
+               /// </summary>
+               public bool HasItemTemplates => ItemTemplates.Count > 0;
 
                /// <summary>
                /// 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 ();
+                       }
+               }
+               /// <summary>
+               /// load ItemTemplate(s) from ItemTemplate property
+               /// </summary>
+               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);
index c114fb3f91c48ea58eb6ac1a6831280617ae81ef..512d27e0f4a70a387034f251b14bcbbd4dc9eea2 100644 (file)
@@ -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);
                        }
index fabf4b4545d625b243aff7b1c3fd3d294d55ed05..17af62824c1eaafc72a319cbcf928689ed13b3b3 100644 (file)
@@ -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<Measures>.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 (file)
index 99279cd..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0"?>
-<Window Width="500" Height="300" MinimumSize="50,50">
-<HorizontalStack Margin="5" Background="DimGrey">
-       <VerticalStack Width="200" Margin="5" Background="Grey">
-               <VerticalStack Fit="true" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </VerticalStack>
-               <VerticalStack Width="Stretched" Height="Fit" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue" Width="Stretched"/>
-                       <TextRun Background="SkyBlue" Height="Stretched"/>
-               </VerticalStack>
-               <HorizontalStack Fit="true" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-               <HorizontalStack Width="Stretched" Height="Fit" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-                       <HorizontalStack Width="Stretched" Height="Stretched" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue" Width="Stretched"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-       </VerticalStack>
-       <VerticalStack Width="Stretched" Height="Stretched" Margin="5" Background="Grey">
-               <VerticalStack Fit="true" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </VerticalStack>
-               <VerticalStack Width="Stretched" Height="Stretched" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue" Width="Stretched"/>
-                       <TextRun TextAlignment="Center" Background="SkyBlue" Width="Stretched" Height="Stretched"/>
-               </VerticalStack>
-               <HorizontalStack Fit="true" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-               <HorizontalStack Width="Stretched" Height="Fit" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-                       <HorizontalStack Width="Stretched" Height="Fit" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue" Width="Stretched"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-       </VerticalStack>
-       <VerticalStack Width="Fit" Margin="5" Background="Grey">
-               <VerticalStack Width="Stretched" Height="Fit" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue" HorizontalAlignment="Left"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </VerticalStack>
-               <VerticalStack Width="Stretched" Height="Fit" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue" Width="Stretched"/>
-                       <TextRun Background="SkyBlue" Height="Stretched"/>
-               </VerticalStack>
-               <HorizontalStack Fit="true" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-               <HorizontalStack Width="Stretched" Height="Fit" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-                       <HorizontalStack Width="Stretched" Height="Stretched" Background="DimGrey" Margin="5">
-                       <TextRun Background="SkyBlue"/>
-                       <TextRun Background="SkyBlue" Width="Stretched"/>
-                       <TextRun Background="SkyBlue"/>
-               </HorizontalStack>
-       </VerticalStack>
-</HorizontalStack>
-</Window>
\ No newline at end of file