]> O.S.I.I.S - jp/crow.git/commitdiff
:book:, ItemTemplate files handling with multime root, Content made mandatory in...
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 5 Feb 2018 19:51:26 +0000 (20:51 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 5 Feb 2018 19:51:26 +0000 (20:51 +0100)
17 files changed:
Crow.Test/Crow.Test.csproj
Crow.csproj
README.md
Templates/FileDialog.template
Templates/FileItems.template [new file with mode: 0644]
src/GraphicObjects/Button.cs
src/GraphicObjects/Expandable.cs
src/GraphicObjects/GraphicObject.cs
src/GraphicObjects/GroupBox.cs
src/GraphicObjects/Popper.cs
src/GraphicObjects/TabItem.cs
src/GraphicObjects/TemplatedContainer.cs
src/GraphicObjects/TemplatedControl.cs
src/GraphicObjects/TemplatedGroup.cs
src/GraphicObjects/Window.cs
src/Instantiator.cs
src/ItemTemplate.cs

index 94ec07b88d403b5d844671785175d32baf91c8c9..fe1bbca7a671c1c72ed34c1736672062db1c798d 100644 (file)
@@ -10,6 +10,7 @@
     <RootNamespace>Crow.Test</RootNamespace>
     <AssemblyName>Crow.Test</AssemblyName>
     <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <ReleaseVersion>0.5</ReleaseVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
index b58634dbbc1c16354befaf1d9ed81e4cd86e3305..e6cf6864ce152779ed7ddbe9b856bf352bb3f463 100644 (file)
     <EmbeddedResource Include="Templates\DockingView.template">
       <LogicalName>Crow.DockingView.template</LogicalName>
     </EmbeddedResource>
+    <EmbeddedResource Include="Templates\FileItems.template" />
   </ItemGroup>
   <ItemGroup>
     <None Include="Crow.dll.config">
index 17ecb240dd253604e10903d3b6201e63bbe37d0e..cfd9cde4d26b1a19e50f9756724b782138e6a58a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -23,6 +23,7 @@
 </p>
 </h1>
 
+## Presentation
 **C.R.O.W.** is a [widget toolkit](https://en.wikipedia.org/wiki/Widget_toolkit) and
 rendering engine entirely developed in **C#**, offering a nice trade-off between
 complexity of language and performances. Crow provides a declarative interface language
@@ -36,16 +37,25 @@ for easy c# code linking.
   </a>
 </p>
 
-For **documentation** and **tutorials** visit the [Wiki](https://github.com/jpbruyere/Crow/wiki)
-or the [Project Site](https://jpbruyere.github.io/Crow/).
+#### Features
+- [Declarative interface definition](interface-markup-language).
+- [Templates](Templates)
+- [Styling](Styling)
+- [Dynamic binding system](The-binding-system)
+- SVG rendering (with [rsvg library](https://developer.gnome.org/rsvg/))
+
+#### Documentation
+* [Introduction](Global-architecture)
+* [Classes documentation autogenerated from doxygen](index)
+* [Tutorials](Tutorials)
 
 Please report bugs and issues on [GitHub](https://github.com/jpbruyere/Crow/issues)
 
 ## Getting Start
 
 ### Requirements
-- [mono > 5.0](http://www.mono-project.com/download/)
-- [Cairo Graphic Library](https://cairographics.org/) >= 1.1
+- [mono >= 5.0](http://www.mono-project.com/download/)
+- [Cairo Graphic Library](https://cairographics.org/) >= 1.2
 - [rsvg library](https://developer.gnome.org/rsvg/) for svg rendering
 - [nuget](https://www.nuget.org/).
 
index 8305dfc93bccae8ca91d9653f55e4f0ec1de8429..7eba68281edfb80e91ae3af16dd3f08dffca2f0c 100644 (file)
@@ -28,7 +28,8 @@
                                <DirectoryView ShowFiles="true" Name="fv" CurrentDirectory="{./CurrentDirectory}" SelectedItemChanged="./onFVSelectedItemChanged"
                                                Width="100%" Margin="0" MouseDoubleClick="./onFileSelect">
                                                <Template>
-                                                       <ListBox Name="fileView" Data="{./FileSystemEntries}" SelectedItemChanged="./onSelectedItemChanged">
+                                                       <ListBox ItemTemplate="#Crow.Templates.FileItems.template" Name="fileView" Data="{./FileSystemEntries}"
+                                                               SelectedItemChanged="./onSelectedItemChanged">
                                                                <Template>
                                                                        <HorizontalStack>
                                                                                <Scroller ScrollX="{../scrollbar1.Value}"  Name="scroller1"
                                                                                        Width="14" />
                                                                        </HorizontalStack>
                                                                </Template>
-                                                               <ItemTemplate DataType="System.IO.FileInfo">
-                                                                       <HorizontalStack Focusable="true"  Height="Fit">
-                                                                               <Image Margin="2" Width="16" Height="16"
-                                                                                       Path="#Crow.Icons.file.svg"/>
-                                                                                       <Label Text="{Name}" Width="Stretched"
-                                                                                               MouseEnter="{Background=BlueCrayola}"
-                                                                                               MouseLeave="{Background=Transparent}"/>
-                                                                       </HorizontalStack>
-                                                               </ItemTemplate>
-                                                               <ItemTemplate DataType="System.IO.DirectoryInfo">
-                                                                       <Border Foreground="Transparent" Focusable="true" Height="Fit">
-                                                                               <HorizontalStack
-                                                                                               MouseEnter="{Background=BlueCrayola}"
-                                                                                               MouseLeave="{Background=Transparent}">
-                                                                                       <Image Margin="2" Width="16" Height="16"
-                                                                                               Path="#Crow.Icons.folder.svg"/>
-                                                                                       <Label Text="{Name}" Width="Stretched"/>
-                                                                                       <Label Text="{LastAccessTime}" />
-                                                                               </HorizontalStack>
-                                                                       </Border>
-                                                               </ItemTemplate>
                                                        </ListBox>
                                                </Template>
                                        </DirectoryView>
diff --git a/Templates/FileItems.template b/Templates/FileItems.template
new file mode 100644 (file)
index 0000000..99d7b6a
--- /dev/null
@@ -0,0 +1,25 @@
+<ItemTemplate>
+       <GraphicObject Height="16" Background="Red"/>
+</ItemTemplate>
+<ItemTemplate DataType="System.IO.FileInfo">
+       <HorizontalStack Focusable="true"  Height="Fit">
+               <Image Margin="2" Width="16" Height="16"
+                       Path="#Crow.Icons.file.svg"/>
+                       <Label Text="{Name}" Width="Stretched"
+                               MouseEnter="{Background=BlueCrayola}"
+                               MouseLeave="{Background=Transparent}"/>
+       </HorizontalStack>
+</ItemTemplate>
+<ItemTemplate DataType="System.IO.DirectoryInfo">
+       <Border Foreground="Transparent" Focusable="true" Height="Fit">
+               <HorizontalStack
+                               MouseEnter="{Background=BlueCrayola}"
+                               MouseLeave="{Background=Transparent}">
+                       <Image Margin="2" Width="16" Height="16"
+                               Path="#Crow.Icons.folder.svg"/>
+                       <Label Text="{Name}" Width="Stretched"/>
+                       <Label Text="{LastAccessTime}" />
+               </HorizontalStack>
+       </Border>
+</ItemTemplate>
+
index 5967d94e7490927df9acf65f0090e4c73eeaa9f3..d4b954570b6e1bc9204e06c16d81b5ed9d928395 100644 (file)
@@ -54,24 +54,6 @@ namespace Crow
                public event EventHandler Pressed;
                public event EventHandler Released;
 
-               #region TemplatedContainer overrides
-               public override GraphicObject Content {
-                       get {
-                               return _contentContainer == null ? null : _contentContainer.Child;
-                       }
-                       set {
-                               if (_contentContainer != null)
-                                       _contentContainer.SetChild(value);
-                       }
-               }
-               protected override void loadTemplate(GraphicObject template = null)
-               {
-                       base.loadTemplate (template);
-
-                       _contentContainer = this.child.FindByName ("Content") as Container;
-               }
-               #endregion
-
                #region GraphicObject Overrides
                public override void onMouseDown (object sender, MouseButtonEventArgs e)
                {
index 2328fd5f00acaf65f40f49aa8eb6c3126cd53906..43f44a93facf0c5e355c3fe7788240e526fbb141 100644 (file)
@@ -65,25 +65,6 @@ namespace Crow
                {
                        IsExpanded = !IsExpanded;
                }
-               /// <summary>
-               /// Implement the abstract Content property of TemplatedControl
-               /// </summary>
-               public override GraphicObject Content {
-                       get {
-                               return _contentContainer == null ? null : _contentContainer.Child;
-                       }
-                       set {
-                               _contentContainer.SetChild(value);
-                               NotifyValueChanged ("HasContent", HasContent);
-                       }
-               }
-               //TODO: move loadTemplate and ResolveBinding in TemplatedContainer
-               protected override void loadTemplate(GraphicObject template = null)
-               {
-                       base.loadTemplate (template);
-
-                       _contentContainer = this.child.FindByName ("Content") as Container;
-               }
 
                #region Public properties
                [XmlAttributeAttribute][DefaultValue("#Crow.Images.Icons.expandable.svg")]
@@ -120,9 +101,6 @@ namespace Crow
                                        onCollapse (this, null);
             }
         }
-               [XmlIgnore]public bool HasContent {
-                       get { return _contentContainer == null ? false : _contentContainer.Child != null; }
-               }
                [XmlIgnore]public bool IsExpandable {
                        get {
                                try {
index b7ca11f61a44c93983cb637b586ebadd17bacab3..3da8330d85aaf391ce27834c2189b843ae385df3 100644 (file)
@@ -205,10 +205,10 @@ namespace Crow
                public Rectangle LastSlots;
                /// <summary>
                /// keep last slot painted on screen to clear traces if moved or resized
-               /// TODO: we should ensure the whole parsed widget tree is the last painted
                /// version to clear effective oldslot if parents have been moved or resized.
                /// IDEA is to add a ScreenCoordinates function that use only lastPaintedSlots
                /// </summary>
+               //TODO: we should ensure the whole parsed widget tree is the last painted
                public Rectangle LastPaintedSlot;
                /// <summary>Prevent requeuing multiple times the same widget</summary>
                public bool IsQueueForRedraw = false;
index e5a170ae9ee5fd02fc9c90b68d86bfc48db5d517..61e7f2af99cbfcfc8d35c1ed0634b842b171271d 100644 (file)
@@ -39,22 +39,5 @@ namespace Crow
                public GroupBox () : base(){}
                public GroupBox(Interface iface) : base(iface){}
                #endregion
-
-               #region TemplatedContainer implementation
-               public override GraphicObject Content {
-                       get {
-                               return _contentContainer == null ? null : _contentContainer.Child;
-                       }
-                       set {
-                               _contentContainer.SetChild(value);
-                       }
-               }
-               protected override void loadTemplate(GraphicObject template = null)
-               {
-                       base.loadTemplate (template);
-
-                       _contentContainer = this.child.FindByName ("Content") as Container;
-               }
-               #endregion
        }
 }
index 175c99fd172ea5ac758fc0e81d3f544733bd4bd6..9f60aa4022f26b84d0a1cf7a3c50a8c78e64ed43 100644 (file)
@@ -39,7 +39,7 @@ namespace Crow
 
                bool _isPopped, _canPop;
                Alignment popDirection;
-               GraphicObject _contentContainer;
+               GraphicObject _content;
                Measure popWidth, popHeight;
 
                public event EventHandler Popped;
@@ -111,22 +111,22 @@ namespace Crow
                #endregion
 
                public override GraphicObject Content {
-                       get { return _contentContainer; }
+                       get { return _content; }
                        set {
-                               if (_contentContainer != null) {
-                                       _contentContainer.LogicalParent = null;
-                                       _contentContainer.LayoutChanged -= _content_LayoutChanged;
+                               if (_content != null) {
+                                       _content.LogicalParent = null;
+                                       _content.LayoutChanged -= _content_LayoutChanged;
                                }
 
-                               _contentContainer = value;
+                               _content = value;
 
-                               if (_contentContainer == null)
+                               if (_content == null)
                                        return;
 
-                               _contentContainer.LogicalParent = this;
-                               _contentContainer.HorizontalAlignment = HorizontalAlignment.Left;
-                               _contentContainer.VerticalAlignment = VerticalAlignment.Top;
-                               _contentContainer.LayoutChanged += _content_LayoutChanged;
+                               _content.LogicalParent = this;
+                               _content.HorizontalAlignment = HorizontalAlignment.Left;
+                               _content.VerticalAlignment = VerticalAlignment.Top;
+                               _content.LayoutChanged += _content_LayoutChanged;
                        }
                }
                void positionContent(LayoutingType lt){
@@ -242,9 +242,9 @@ namespace Crow
 
                protected override void Dispose (bool disposing)
                {
-                       if (_contentContainer != null && disposing) {
-                               if (_contentContainer.Parent == null)
-                                       _contentContainer.Dispose ();
+                       if (_content != null && disposing) {
+                               if (_content.Parent == null)
+                                       _content.Dispose ();
                        }
                        base.Dispose (disposing);
                }
index 9dfff864745fa277707913891432e21b562ad4c1..b19d14e8717f946ea213944ece4f8fb7eac13595 100644 (file)
@@ -65,7 +65,6 @@ namespace Crow
                {
                        base.loadTemplate (template);
 
-                       _contentContainer = this.child.FindByName ("Content") as Container;
                        titleWidget = this.child.FindByName ("TabTitle");
                }
                internal GraphicObject TabTitle { get { return titleWidget; }}
index 02c14d381d26a4c7abd8dc8b95fff6e1c155c2a2..a2e35eabd28a1f3f11e79d70669df585522bfcfa 100644 (file)
@@ -31,7 +31,12 @@ using System.Reflection;
 
 namespace Crow
 {
-       public abstract class TemplatedContainer : TemplatedControl
+       /// <summary>
+       /// base class for new containers that will use templates.
+       /// 
+       /// TemplatedControl's **must** provide a widget of the [`Container`](Container) class named **_'Content'_** inside their template tree
+       /// </summary>
+       public class TemplatedContainer : TemplatedControl
        {
                #region CTOR
                public TemplatedContainer() : base(){}
@@ -40,7 +45,27 @@ namespace Crow
 
                protected Container _contentContainer;
 
-               [XmlAttributeAttribute]public virtual GraphicObject Content{ get; set;}
+               /// <summary>
+               /// Single child of this templated container.
+               /// </summary>
+               public virtual GraphicObject Content {
+                       get {
+                               return _contentContainer == null ? null : _contentContainer.Child;
+                       }
+                       set {
+                               _contentContainer.SetChild(value);
+                               NotifyValueChanged ("HasContent", HasContent);
+                       }
+               }
+               [XmlIgnore]public bool HasContent {
+                       get { return _contentContainer?.Child != null; }
+               }
+               //TODO: move loadTemplate and ResolveBinding in TemplatedContainer
+               protected override void loadTemplate(GraphicObject template = null)
+               {
+                       base.loadTemplate (template);
+                       _contentContainer = this.child.FindByName ("Content") as Container;
+               }
 
                #region GraphicObject overrides
                public override GraphicObject FindByName (string nameToFind)
index 6e236c8d71c730155a9f68c171d5b0d667fa1d25..a3a6b1422e134f3ffae08b4655aae414e1fa2a55 100644 (file)
@@ -54,6 +54,7 @@ namespace Crow
                /// <summary>
                /// Template path
                /// </summary>
+               //TODO: this property should be renamed 'TemplatePath'
                [XmlAttributeAttribute][DefaultValue(null)]
                public string Template {
                        get { return _template; }
@@ -69,7 +70,7 @@ namespace Crow
                        }
                }
                /// <summary>
-               /// caption property being recurrent in templated widget, it is declared here.
+               /// a caption being recurrent need in templated widget, it is declared here.
                /// </summary>
                [XmlAttributeAttribute()][DefaultValue("Templated Control")]
                public virtual string Caption {
index aaeb77f64965e735d9581c0893ea432980df2daf..81ea25fbcfebf2eb6929a4d51d09ba1d8567d6d9 100644 (file)
@@ -67,7 +67,11 @@ namespace Crow
                public Dictionary<string, ItemTemplate> ItemTemplates = new Dictionary<string, Crow.ItemTemplate>();
 
                /// <summary>
-               /// Default item template
+               /// Item templates file path, on disk or embedded.
+               /// 
+               /// ItemTemplate file may contains either a single template without the
+               /// ItemTemplate enclosing tag, or several item templates each enclosed
+               /// in a separate tag
                /// </summary>
                [XmlAttributeAttribute][DefaultValue("#Crow.Templates.ItemTemplate.goml")]
                public string ItemTemplate {
@@ -272,10 +276,8 @@ namespace Crow
                /// Items loading thread
                /// </summary>
                void loading(){
-                       if (ItemTemplates == null)
-                               ItemTemplates = new Dictionary<string, ItemTemplate> ();
-                       if (!ItemTemplates.ContainsKey ("default"))
-                               ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
+                       //if (!ItemTemplates.ContainsKey ("default"))
+                       //      ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
 
                        for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) {
                                if ((bool)loadingThread?.cancelRequested) {
index d1f3437483c4f7a550572667fde44014b3d846d3..efc8f4e390df12085a7f4baee292de2fb7906e2e 100644 (file)
@@ -70,14 +70,9 @@ namespace Crow
                #endregion
 
                #region TemplatedContainer overrides
-               public override GraphicObject Content {
-                       get { return _contentContainer == null ? null : _contentContainer.Child; }
-                       set { _contentContainer.SetChild(value); }
-               }
                protected override void loadTemplate(GraphicObject template = null)
                {
                        base.loadTemplate (template);
-                       _contentContainer = this.child.FindByName ("Content") as Container;
 
                        NotifyValueChanged ("ShowNormal", false);
                        NotifyValueChanged ("ShowMinimize", true);
index 902092e2228efd045c56961e22c7a44f3e0d21b7..5f187c58c20af034460188666519778ca4fec464 100644 (file)
@@ -82,15 +82,23 @@ namespace Crow.IML
                        Stopwatch loadingTime = new Stopwatch ();
                        loadingTime.Start ();
 #endif
-                       using (XmlTextReader itr = new XmlTextReader (stream)) {
+                       using (XmlReader itr = XmlReader.Create (stream)) {
                                parseIML (itr);
                        }
+                       stream.Dispose ();
 #if DEBUG_LOAD
                        loadingTime.Stop ();
                        Debug.WriteLine ("IML Instantiator creation '{2}' : {0} ticks, {1} ms",
                                loadingTime.ElapsedTicks, loadingTime.ElapsedMilliseconds, imlPath);
 #endif
                }
+               /// <summary>
+               /// Initializes a new instance of the Instantiator class with an already openned xml reader
+               /// positionned on the start tag inside the itemTemplate
+               /// </summary>
+               public Instantiator (XmlReader itr){
+                       parseIML (itr);
+               }
                //TODO:check if still used
                public Instantiator (Type _root, InstanciatorInvoker _loader)
                {
@@ -144,7 +152,7 @@ namespace Crow.IML
                /// <summary>
                /// Parses IML and build a dynamic method that will be used to instanciate one or multiple occurence of the IML file or fragment
                /// </summary>
-               void parseIML (XmlTextReader reader) {
+               void parseIML (XmlReader reader) {
                        IMLContext ctx = new IMLContext (findRootType (reader));
 
                        ctx.nodesStack.Push (new Node (ctx.RootType));
@@ -169,21 +177,21 @@ namespace Crow.IML
                /// read first node to set GraphicObject class for loading
                /// and let reader position on that node
                /// </summary>
-               Type findRootType (XmlTextReader reader)
+               Type findRootType (XmlReader reader)
                {
                        string root = "Object";
-                       while (reader.Read ()) {
-                               if (reader.NodeType == XmlNodeType.Element) {
-                                       root = reader.Name;
-                                       break;
-                               }
-                       }
+                       while (reader.NodeType != XmlNodeType.Element)
+                               reader.Read ();
+                       root = reader.Name;
                        Type t = tryGetGOType (root);
                        if (t == null)
                                throw new Exception ("IML parsing error: undefined root type (" + root + ")");
                        return t;
                }
-               void emitLoader (XmlTextReader reader, IMLContext ctx)
+               /// <summary>
+               /// main parsing entry point
+               /// </summary>
+               void emitLoader (XmlReader reader, IMLContext ctx)
                {
                        string tmpXml = reader.ReadOuterXml ();
 
@@ -195,6 +203,41 @@ namespace Crow.IML
                        //emitCheckAndBindValueChanged (ctx);
                }
                /// <summary>
+               /// Parses the item template tag.
+               /// </summary>
+               /// <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 = "") {
+                       string dataType = "default", datas = "", path = "";
+                       while (reader.MoveToNextAttribute ()) {
+                               if (reader.Name == "DataType")
+                                       dataType = reader.Value;
+                               else if (reader.Name == "Data")
+                                       datas = reader.Value;
+                               else if (reader.Name == "Path")
+                                       path = reader.Value;
+                       }
+                       reader.MoveToElement ();
+
+                       string itemTmpID = itemTemplatePath;
+
+                       if (string.IsNullOrEmpty (path)) {
+                               itemTmpID += Guid.NewGuid ().ToString ();
+                               Interface.Instantiators [itemTmpID] =
+                                       new ItemTemplate (new MemoryStream (Encoding.UTF8.GetBytes (reader.ReadInnerXml ())), dataType, datas);
+
+                       } else {
+                               if (!reader.IsEmptyElement)
+                                       throw new Exception ("ItemTemplate with Path attribute set may not include sub nodes");
+                               itemTmpID += path+dataType+datas;
+                               if (!Interface.Instantiators.ContainsKey (itemTmpID))
+                                       Interface.Instantiators [itemTmpID] =
+                                               new ItemTemplate (Interface.GetStreamFromPath (path), dataType, datas);
+                       }
+                       return new string [] { dataType, itemTmpID, datas };
+               }
+               /// <summary>
                /// process template and item template definition prior to
                /// other attributes or childs processing
                /// </summary>
@@ -208,6 +251,7 @@ namespace Crow.IML
 
                                reader.Read ();
                                string templatePath = reader.GetAttribute ("Template");
+                               string itemTemplatePath = reader.GetAttribute ("ItemTemplate");
 
                                int depth = reader.Depth + 1;
                                while (reader.Read ()) {
@@ -217,35 +261,8 @@ namespace Crow.IML
                                                inlineTemplate = true;
                                                reader.Read ();
                                                readChildren (reader, ctx, -1);
-                                       } else if (reader.Name == "ItemTemplate") {
-                                               string dataType = "default", datas = "", path = "";
-                                               while (reader.MoveToNextAttribute ()) {
-                                                       if (reader.Name == "DataType")
-                                                               dataType = reader.Value;
-                                                       else if (reader.Name == "Data")
-                                                               datas = reader.Value;
-                                                       else if (reader.Name == "Path")
-                                                               path = reader.Value;
-                                               }
-                                               reader.MoveToElement ();
-
-                                               string itemTmpID;
-
-                                               if (string.IsNullOrEmpty (path)) {
-                                                       itemTmpID = Guid.NewGuid ().ToString ();
-                                                       Interface.Instantiators [itemTmpID] =
-                                                               new ItemTemplate (new MemoryStream (Encoding.UTF8.GetBytes (reader.ReadInnerXml ())), dataType, datas);
-
-                                               } else {
-                                                       if (!reader.IsEmptyElement)
-                                                               throw new Exception ("ItemTemplate with Path attribute may not include sub nodes");
-                                                       itemTmpID = path+dataType+datas;
-                                                       if (!Interface.Instantiators.ContainsKey (itemTmpID))
-                                                               Interface.Instantiators [itemTmpID] =
-                                                                                new ItemTemplate (Interface.GetStreamFromPath (itemTmpID), dataType, datas);
-                                               }
-                                               itemTemplateIds.Add (new string [] { dataType, itemTmpID, datas });
-                                       }
+                                       } else if (reader.Name == "ItemTemplate")
+                                               itemTemplateIds.Add (parseItemTemplateTag (reader));                                    
                                }
 
                                if (!inlineTemplate) {//load from path or default template
@@ -260,6 +277,36 @@ namespace Crow.IML
                                        }
                                        ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miLoadTmp);//load template
                                }
+                               if (itemTemplateIds.Count == 0) {
+                                       //try to load ItemTemplate(s) from ItemTemplate attribute of TemplatedGroup
+                                       if (!string.IsNullOrEmpty (itemTemplatePath)) {
+                                               //check if it is already loaded in cache as a single itemTemplate instantiator
+                                               if (Interface.Instantiators.ContainsKey (itemTemplatePath)) {
+                                                       itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "" });
+                                               } else {
+                                                       using (Stream stream = Interface.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 != "ItemTemplate") {
+                                                                                               //the file contains a single template to use as default
+                                                                                               Interface.Instantiators [itemTemplatePath] =
+                                                                                                       new ItemTemplate (itr);
+                                                                                               itemTemplateIds.Add (new string [] { "default", itemTemplatePath, "" });
+                                                                                               break;//we should be at the end of the file
+                                                                                       }
+                                                                                       itemTemplateIds.Add (parseItemTemplateTag (itr, itemTemplatePath));
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
                                //copy item templates (review this)
                                foreach (string [] iTempId in itemTemplateIds) {
                                        ctx.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
index d866bc192e3c11dde9ea785b7b041fa0a5790343..d0c6873e62ec4b305ebf0c72548992c60d5743e4 100644 (file)
@@ -63,6 +63,12 @@ namespace Crow
                        strDataType = _dataType;
                        fetchMethodName = _fetchDataMethod;
                }
+               public ItemTemplate (XmlReader reader, string _dataType = null, string _fetchDataMethod = null)
+                       :base(reader)
+               {
+                       strDataType = _dataType;
+                       fetchMethodName = _fetchDataMethod;
+               }
                #endregion
 
                public void CreateExpandDelegate (TemplatedGroup host){