]> O.S.I.I.S - jp/crow.git/commitdiff
first working test with hierarchical TemplatedGroup with only one root Level
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 17 Feb 2018 11:13:48 +0000 (12:13 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 17 Feb 2018 11:13:48 +0000 (12:13 +0100)
Templates/DirectoryView.template
src/CompilerServices/CompilerServices.cs
src/GraphicObjects/TemplatedGroup.cs
src/Instantiator.cs
src/ItemTemplate.cs

index 42e9020ff8cca2ca3ca73dc13a0c7b94d163b9d5..826dd3f83d78fb6b9ce3ac2ce1cb6bcc017245c4 100755 (executable)
@@ -37,8 +37,7 @@
                        </Template>
                        <HorizontalStack Height="Fit">
                                <GraphicObject Width="12" Height="10"/>
-                               <TreeView Name="List" Height="Fit"
-                                       Template="#Crow.Templates.treeList.template" />
+                               <VerticalStack Height="Fit" Name="ItemsContainer"/>
                        </HorizontalStack>
                </Expandable>
        </ItemTemplate>
index 16d28490df0a446b6e8d85cc41941b7ca0080329..dbd12d414c14a8f02a5cd80b19f5a2b47506d0b2 100644 (file)
@@ -92,6 +92,9 @@ 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 miLoadPage = typeof(TemplatedGroup).GetMethod ("loadPage", BindingFlags.Instance | BindingFlags.NonPublic| BindingFlags.Public);
+               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);
                #region tree handling methods
index ef099f933a4b3590cee225c3d4d16cde4508fda5..c72bfbcb69aa4fe2fdb17dcbd767f2f0ec168229 100644 (file)
@@ -34,6 +34,7 @@ using System.Collections;
 using System.Threading;
 using System.Linq;
 using Crow.IML;
+using System.Diagnostics;
 
 namespace Crow
 {
@@ -45,7 +46,7 @@ namespace Crow
                #endregion
 
                protected Group items;
-               string _itemTemplate, _dataTest;
+               string _itemTemplate, dataTest;
 
                #region events
                public event EventHandler<SelectionChangeEventArgs> SelectedItemChanged;
@@ -66,6 +67,11 @@ namespace Crow
                //but then i should test if null in msil gen
                public Dictionary<string, ItemTemplate> ItemTemplates = new Dictionary<string, Crow.ItemTemplate>();
 
+               /// <summary>
+               /// Keep track of expanded subnodes and closed time to unload
+               /// </summary>
+               //Dictionary<GraphicObject, Stopwatch> nodes = new Dictionary<GraphicObject, Stopwatch>();
+               internal List<GraphicObject> nodes = new List<GraphicObject>();
                /// <summary>
                /// Item templates file path, on disk or embedded.
                /// 
@@ -106,14 +112,14 @@ namespace Crow
                /// <value>The data property test.</value>
                [XmlAttributeAttribute][DefaultValue("TypeOf")]
                public string DataTest {
-                       get { return _dataTest; }
+                       get { return dataTest; }
                        set {
-                               if (value == _dataTest)
+                               if (value == dataTest)
                                        return;
 
-                               _dataTest = value;
+                               dataTest = value;
 
-                               NotifyValueChanged("DataTest", _dataTest);
+                               NotifyValueChanged("DataTest", dataTest);
                        }
                }
                #endregion
@@ -170,7 +176,7 @@ namespace Crow
                                if (value == data)
                                        return;
 
-                               cancelLoadingThread ();
+                               //cancelLoadingThread ();
 
                                if (data is IObservableList) {
                                        IObservableList ol = data as IObservableList;
@@ -188,15 +194,17 @@ namespace Crow
 
                                NotifyValueChanged ("Data", data);
 
-                               lock (CurrentInterface.LayoutMutex)
+                               //lock (CurrentInterface.LayoutMutex)
                                        ClearItems ();
 
                                if (data == null)
                                        return;
 
-                               loadingThread = new CrowThread (this, loading);
-                               loadingThread.Finished += (object sender, EventArgs e) => (sender as TemplatedGroup).Loaded.Raise (sender, e);
-                               loadingThread.Start ();
+//                             loadingThread = new CrowThread (this, loading);
+//                             loadingThread.Finished += (object sender, EventArgs e) => (sender as TemplatedGroup).Loaded.Raise (sender, e);
+//                             loadingThread.Start ();
+
+                               loadPage (data, items, dataTest);
 
                                NotifyValueChanged ("SelectedIndex", _selectedIndex);
                                NotifyValueChanged ("SelectedItem", SelectedItem);
@@ -223,7 +231,7 @@ namespace Crow
 //                             int i = e.Index % itemPerPage;
 //                             (items.Children [p] as Group).InsertChild (i, e.Element);
                        } else
-                               loadItem (e.Index, items);
+                               loadItem (e.Element, items, dataTest);
                }
 
                [XmlAttributeAttribute][DefaultValue("SteelBlue")]
@@ -319,69 +327,62 @@ namespace Crow
                /// <summary>
                /// Items loading thread
                /// </summary>
-               void loading(){
-                       //if (!ItemTemplates.ContainsKey ("default"))
-                       //      ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
-
-                       for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) {
-                               if ((bool)loadingThread?.cancelRequested) {
-                                       this.Dispose ();
-                                       return;
-                               }
-                               loadPage (i);
-                               Thread.Sleep (1);
-                       }
-               }
+//             void loading(){
+//                     //if (!ItemTemplates.ContainsKey ("default"))
+//                     //      ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
+//
+//                     for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) {
+//                             if ((bool)loadingThread?.cancelRequested) {
+//                                     this.Dispose ();
+//                                     return;
+//                             }
+//                             loadPage (i);
+//                             Thread.Sleep (1);
+//                     }
+//             }
                void cancelLoadingThread(){
                        if (loadingThread != null)
                                loadingThread.Cancel ();
                }
-               void loadPage(int pageNum)
+               void loadPage(IList _data, Group page, string _dataTest)
                {
                        #if DEBUG_LOAD
                        Stopwatch loadingTime = new Stopwatch ();
                        loadingTime.Start ();
                        #endif
 
-                       Group page;
-                       if (typeof(TabView).IsAssignableFrom (items.GetType ())||
-                               typeof(Menu).IsAssignableFrom (this.GetType())||
-                               typeof(Wrapper).IsAssignableFrom (items.GetType ())) {
-                               page = items;
-                               itemPerPage = int.MaxValue;
-                       } else if (typeof(GenericStack).IsAssignableFrom (items.GetType ())) {
-                               GenericStack gs = new GenericStack (items.CurrentInterface);
-                               gs.Orientation = (items as GenericStack).Orientation;
-                               gs.Width = items.Width;
-                               gs.Height = items.Height;
-                               gs.VerticalAlignment = items.VerticalAlignment;
-                               gs.HorizontalAlignment = items.HorizontalAlignment;
-                               page = gs;
-                               page.Name = "page" + pageNum;
-                               isPaged = true;
-                       } else {
-                               page = Activator.CreateInstance (items.GetType ()) as Group;
-                               page.CurrentInterface = items.CurrentInterface;
-                               page.Initialize ();
-                               page.Name = "page" + pageNum;
-                               isPaged = true;
-                       }
-
-                       for (int i = (pageNum - 1) * itemPerPage; i < pageNum * itemPerPage; i++) {
-                               if (i >= data.Count)
-                                       break;
-                               if ((bool)loadingThread?.cancelRequested) {
-                                       page.Dispose ();
-                                       return;
-                               }
 
-                               loadItem (i, page);
+//                     if (typeof(TabView).IsAssignableFrom (items.GetType ())||
+//                             typeof(Menu).IsAssignableFrom (this.GetType())||
+//                             typeof(Wrapper).IsAssignableFrom (items.GetType ())) {
+                               //page = items;
+                               itemPerPage = int.MaxValue;
+//                     } else if (typeof(GenericStack).IsAssignableFrom (items.GetType ())) {
+//                             GenericStack gs = new GenericStack (items.CurrentInterface);
+//                             gs.Orientation = (items as GenericStack).Orientation;
+//                             gs.Width = items.Width;
+//                             gs.Height = items.Height;
+//                             gs.VerticalAlignment = items.VerticalAlignment;
+//                             gs.HorizontalAlignment = items.HorizontalAlignment;
+//                             page = gs;
+//                             page.Name = "page" + pageNum;
+//                             isPaged = true;
+//                     } else {
+//                             page = Activator.CreateInstance (items.GetType ()) as Group;
+//                             page.CurrentInterface = items.CurrentInterface;
+//                             page.Initialize ();
+//                             page.Name = "page" + pageNum;
+//                             isPaged = true;
+//                     }
+
+                       for (int i = 0; i < _data.Count; i++) {
+                               loadItem (_data[i], page, _dataTest);
                        }
 
-                       if (page == items)
-                               return;
-                       lock (CurrentInterface.LayoutMutex)
-                               items.AddChild (page);
+//                     if (page == items)
+//                             return;
+//                     lock (CurrentInterface.LayoutMutex)
+//                             items.AddChild (page);
 
                        #if DEBUG_LOAD
                        loadingTime.Stop ();
@@ -390,23 +391,23 @@ namespace Crow
                        loadingTime.ElapsedMilliseconds, this.ToString());
                        #endif
                }
-               string getItempKey(Type dataType, object o){
+               string getItempKey(Type dataType, object o, string propertyName){
                        try {
-                               return dataType.GetProperty (_dataTest).GetGetMethod ().Invoke (o, null)?.ToString();
+                               return dataType.GetProperty (propertyName).GetGetMethod ().Invoke (o, null)?.ToString();
                        } catch  {
                                return dataType.FullName;
                        }
                }
-               protected void loadItem(int i, Group page){
-                       if (data [i] == null)//TODO:surely a threading sync problem
+               protected void loadItem(object o, Group page, string _dataTest){
+                       if (o == null)//TODO:surely a threading sync problem
                                return;
                        GraphicObject g = null;
                        ItemTemplate iTemp = null;
-                       Type dataType = data [i].GetType ();
+                       Type dataType = o.GetType ();
                        string itempKey = dataType.FullName;
 
                        if (_dataTest != "TypeOf")
-                               itempKey = getItempKey (dataType, data [i]);
+                               itempKey = getItempKey (dataType, o, _dataTest);
 
                        if (ItemTemplates.ContainsKey (itempKey))
                                iTemp = ItemTemplates [itempKey];
@@ -437,7 +438,7 @@ namespace Crow
                                (g as Expandable).GetIsExpandable = iTemp.HasSubItems;
                        }
 
-                       g.DataSource = data [i];
+                       g.DataSource = o;
                }
                protected virtual void registerItemClick(GraphicObject g){
                        g.MouseClick += itemClick;
@@ -475,6 +476,13 @@ namespace Crow
                        SelectedIndex = data.IndexOf((sender as GraphicObject).DataSource);
                }
 
+               bool emitHelperIsAlreadyExpanded (GraphicObject go){
+                       if (nodes.Contains (go))
+                               return true;
+                       nodes.Add (go);
+                       return false;
+               }
+
                protected override void Dispose (bool disposing)
                {
                        if (disposing && loadingThread != null)
index a97f19d251ecd18f2d6126429b9b46f99037c058..b01052ca4961e4c76d362e298cb2166d703f80b0 100644 (file)
@@ -225,7 +225,7 @@ namespace Crow.IML
                /// <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 = "") {
-                       string dataType = "default", datas = "", path = "";
+                       string dataType = "default", datas = "", path = "", dataTest = "TypeOf";
                        while (reader.MoveToNextAttribute ()) {
                                if (reader.Name == "DataType")
                                        dataType = reader.Value;
@@ -233,6 +233,8 @@ namespace Crow.IML
                                        datas = reader.Value;
                                else if (reader.Name == "Path")
                                        path = reader.Value;
+                               else if (reader.Name == "DataTest")
+                                       dataTest = reader.Value;
                        }
                        reader.MoveToElement ();
 
@@ -241,7 +243,7 @@ namespace Crow.IML
                        if (string.IsNullOrEmpty (path)) {
                                itemTmpID += Guid.NewGuid ().ToString ();
                                Interface.Instantiators [itemTmpID] =
-                                       new ItemTemplate (new MemoryStream (Encoding.UTF8.GetBytes (reader.ReadInnerXml ())), dataType, datas);
+                                       new ItemTemplate (new MemoryStream (Encoding.UTF8.GetBytes (reader.ReadInnerXml ())), dataTest, dataType, datas);
 
                        } else {
                                if (!reader.IsEmptyElement)
@@ -249,9 +251,9 @@ namespace Crow.IML
                                itemTmpID += path+dataType+datas;
                                if (!Interface.Instantiators.ContainsKey (itemTmpID))
                                        Interface.Instantiators [itemTmpID] =
-                                               new ItemTemplate (Interface.GetStreamFromPath (path), dataType, datas);
+                                               new ItemTemplate (Interface.GetStreamFromPath (path), dataTest, dataType, datas);
                        }
-                       return new string [] { dataType, itemTmpID, datas };
+                       return new string [] { dataType, itemTmpID, datas, dataTest };
                }
                /// <summary>
                /// process template and item template definition prior to
@@ -312,7 +314,7 @@ namespace Crow.IML
                                                                                                //the file contains a single template to use as default
                                                                                                Interface.Instantiators [itemTemplatePath] =
                                                                                                        new ItemTemplate (itr);
-                                                                                               itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "" });
+                                                                                               itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "", "TypeOf" });
                                                                                                break;//we should be at the end of the file
                                                                                        }
                                                                                        itemTemplateIds.Add (parseItemTemplateTag (itr, itemTemplatePath));
@@ -327,7 +329,7 @@ namespace Crow.IML
                                        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", "" });
+                                       itemTemplateIds.Add (new string [] { "default", "#Crow.DefaultItem.template", "", "TypeOf"});
                                //copy item templates (review this)
                                foreach (string [] iTempId in itemTemplateIds) {
                                        ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
index 52bd520771c4b0604475f9bff76809b96b061c09..5ede1d9455b6cfd58104522bd8dc45e6cc43a93b 100644 (file)
@@ -52,6 +52,7 @@ namespace Crow
                public BooleanTestOnInstance HasSubItems;
                string strDataType;
                string fetchMethodName;
+               string dataTest;
 
                #region CTOR
                /// <summary>
@@ -60,10 +61,11 @@ namespace Crow
                /// <param name="path">IML file to parse</param>
                /// <param name="_dataType">type this item will be choosen for, or member of the data item</param>
                /// <param name="_fetchDataMethod">for hierarchical data, method to call for children fetching</param>
-               public ItemTemplate(string path, string _dataType = null, string _fetchDataMethod = null)
+               public ItemTemplate(string path, string _dataTest = "TypeOf", string _dataType = null, string _fetchDataMethod = null)
                        : base(path) {
                        strDataType = _dataType;
                        fetchMethodName = _fetchDataMethod;
+                       dataTest = _dataTest;
 
                }
                /// <summary>
@@ -72,11 +74,12 @@ namespace Crow
                /// <param name="path">IML fragment to parse</param>
                /// <param name="_dataType">type this item will be choosen for, or member of the data item</param>
                /// <param name="_fetchDataMethod">for hierarchical data, method to call for children fetching</param>
-               public ItemTemplate (Stream ImlFragment, string _dataType, string _fetchDataMethod)
+               public ItemTemplate (Stream ImlFragment, string _dataTest, string _dataType, string _fetchDataMethod)
                        :base(ImlFragment)
                {
                        strDataType = _dataType;
                        fetchMethodName = _fetchDataMethod;
+                       dataTest = _dataTest;
                }
                /// <summary>
                /// Initializes a new instance of the <see cref="Crow.ItemTemplate"/> class using the opened XmlReader in args.
@@ -84,11 +87,12 @@ namespace Crow
                /// <param name="path">XML reader positionned before or at the root node</param>
                /// <param name="_dataType">type this item will be choosen for, or member of the data item</param>
                /// <param name="_fetchDataMethod">for hierarchical data, method to call for children fetching</param>
-               public ItemTemplate (XmlReader reader, string _dataType = null, string _fetchDataMethod = null)
+               public ItemTemplate (XmlReader reader, string _dataTest = "TypeOf" , string _dataType = null, string _fetchDataMethod = null)
                        :base(reader)
                {
                        strDataType = _dataType;
                        fetchMethodName = _fetchDataMethod;
+                       dataTest = _dataTest;
                }
                #endregion
 
@@ -108,7 +112,7 @@ namespace Crow
                        Type tmpGrpType = typeof(TemplatedGroup);
                        Type evtType = typeof(EventHandler);
 
-                       PropertyInfo piData = tmpGrpType.GetProperty ("Data");
+                       //PropertyInfo piData = tmpGrpType.GetProperty ("Data");
 
                        MethodInfo evtInvoke = evtType.GetMethod ("Invoke");
                        ParameterInfo [] evtParams = evtInvoke.GetParameters ();
@@ -120,41 +124,55 @@ namespace Crow
                        //DM is bound to templatedGroup root (arg0)
                        //arg1 is the sender of the expand event
                        DynamicMethod dm = new DynamicMethod ("dyn_expand_" + fetchMethodName,
-                               typeof (void), args, true);
+                               typeof (void), args,typeof(TemplatedGroup), true);
 
                        System.Reflection.Emit.Label gotoEnd;
                        System.Reflection.Emit.Label ifDataIsNull;
+                       System.Reflection.Emit.Label gotoItemsContainerNotFound;
 
                        ILGenerator il = dm.GetILGenerator (256);
                        il.DeclareLocal(typeof(GraphicObject));
 
                        gotoEnd = il.DefineLabel ();
                        ifDataIsNull = il.DefineLabel ();
+                       gotoItemsContainerNotFound = il.DefineLabel ();
 
                        il.Emit (OpCodes.Ldarg_1);//load sender of expand event
-
-                       il.Emit(OpCodes.Ldstr, "List");
+                       il.Emit(OpCodes.Ldstr, "ItemsContainer");//load name to find
                        il.Emit (OpCodes.Callvirt, CompilerServices.miFindByName);
-                       il.Emit (OpCodes.Stloc_0);
+                       il.Emit (OpCodes.Stloc_0);//save items container as loc0
 
-                       //check that 'Data' of list is not already set
+                       //ensure ItemsContainer is not null
                        il.Emit (OpCodes.Ldloc_0);
-                       il.Emit (OpCodes.Callvirt, piData.GetGetMethod ());
-                       il.Emit (OpCodes.Brfalse, ifDataIsNull);
-                       il.Emit (OpCodes.Br, gotoEnd);
+                       il.Emit (OpCodes.Brfalse, gotoItemsContainerNotFound);
+
+                       //check that node is not already expanded
+                       il.Emit (OpCodes.Ldarg_0);//push root TemplatedGroup into the stack
+                       il.Emit (OpCodes.Ldarg_1);
+                       il.Emit (OpCodes.Call, CompilerServices.miIsAlreadyExpanded);
+                       il.Emit (OpCodes.Brtrue, gotoEnd);
+//                     il.Emit (OpCodes.Ldloc_0);
+//                     il.Emit (OpCodes.Callvirt, piData.GetGetMethod ());
+//                     il.Emit (OpCodes.Brfalse, ifDataIsNull);
+//                     il.Emit (OpCodes.Br, gotoEnd);
+
+//                     il.MarkLabel(ifDataIsNull);
 
-                       il.MarkLabel(ifDataIsNull);
                        //copy the ref of ItemTemplates list TODO: maybe find another way to share it among the nodes?
-                       FieldInfo fiTemplates = tmpGrpType.GetField("ItemTemplates");
-                       il.Emit (OpCodes.Ldloc_0);
-                       il.Emit (OpCodes.Ldarg_0);
-                       il.Emit (OpCodes.Ldfld, fiTemplates);
-                       il.Emit (OpCodes.Stfld, fiTemplates);
+//                     FieldInfo fiTemplates = tmpGrpType.GetField("ItemTemplates");
+//                     il.Emit (OpCodes.Ldloc_0);
+//                     il.Emit (OpCodes.Ldarg_0);
+//                     il.Emit (OpCodes.Ldfld, fiTemplates);
+//                     il.Emit (OpCodes.Stfld, fiTemplates);
 
                        //call 'fetchMethodName' from the dataSource to build the sub nodes list
-                       il.Emit (OpCodes.Ldloc_0);//push 'List' (of sub nodes) into the stack
-                       il.Emit (OpCodes.Ldarg_1);//get the dataSource of the sender
-                       il.Emit (OpCodes.Callvirt, CompilerServices.miGetDataSource);
+                       //il.Emit (OpCodes.Ldarg_0);//load root templatedGroop
+
+                       il.Emit (OpCodes.Ldarg_0);//push root TemplatedGroup into the stack
+                       il.Emit (OpCodes.Ldarg_1);//load sender node of expand
+                       il.Emit (OpCodes.Callvirt, CompilerServices.miGetDataSource);//get the dataSource of the sender
+
+
 
                        if (fetchMethodName != "self") {//special keyword self allows the use of recurent list<<<
                                if (dataType == null) {
@@ -167,7 +185,15 @@ namespace Crow
                                        emitGetSubData(il, dataType);                   
                        }
                        //set 'return' from the fetch method as 'data' of the list
-                       il.Emit (OpCodes.Callvirt, piData.GetSetMethod ());
+                       //il.Emit (OpCodes.Callvirt, piData.GetSetMethod ());
+                       il.Emit (OpCodes.Ldloc_0);//load second arg of loadPage, the sender node
+                       il.Emit (OpCodes.Ldstr, dataTest);//load 3rd arg, dataTest kind on subitems
+                       il.Emit (OpCodes.Callvirt, CompilerServices.miLoadPage);
+                       il.Emit (OpCodes.Br, gotoEnd);
+
+                       il.MarkLabel(gotoItemsContainerNotFound);
+                       il.EmitWriteLine("ItemsContainer not found in ItemTemplate for " + host.ToString());
+
 
                        il.MarkLabel(gotoEnd);
                        il.Emit (OpCodes.Ret);
@@ -203,7 +229,6 @@ namespace Crow
                        HasSubItems = (BooleanTestOnInstance)dm.CreateDelegate (typeof(BooleanTestOnInstance));
                        #endregion
                }
-
                //data is on the stack
                void emitGetSubData(ILGenerator il, Type dataType){
                        MethodInfo miGetDatas = dataType.GetMethod (fetchMethodName, new Type[] {});