From: Jean-Philippe Bruyère
Date: Mon, 5 Feb 2018 19:51:26 +0000 (+0100)
Subject: :book:, ItemTemplate files handling with multime root, Content made mandatory in...
X-Git-Tag: v0.9.5-beta~185
X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=6a52a7126e74e1f1b26beb46b89ce6b03dafad2a;p=jp%2Fcrow.git
:book:, ItemTemplate files handling with multime root, Content made mandatory in TemplatedContainer
---
diff --git a/Crow.Test/Crow.Test.csproj b/Crow.Test/Crow.Test.csproj
index 94ec07b8..fe1bbca7 100644
--- a/Crow.Test/Crow.Test.csproj
+++ b/Crow.Test/Crow.Test.csproj
@@ -10,6 +10,7 @@
Crow.Test
Crow.Test
v4.6.1
+ 0.5
true
diff --git a/Crow.csproj b/Crow.csproj
index b58634db..e6cf6864 100644
--- a/Crow.csproj
+++ b/Crow.csproj
@@ -370,6 +370,7 @@
Crow.DockingView.template
+
diff --git a/README.md b/README.md
index 17ecb240..cfd9cde4 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,7 @@
+## 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.
-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.10
+- [mono >= 5.0](http://www.mono-project.com/download/)
+- [Cairo Graphic Library](https://cairographics.org/) >= 1.20
- [rsvg library](https://developer.gnome.org/rsvg/) for svg rendering
- [nuget](https://www.nuget.org/).
diff --git a/Templates/FileDialog.template b/Templates/FileDialog.template
index 8305dfc9..7eba6828 100644
--- a/Templates/FileDialog.template
+++ b/Templates/FileDialog.template
@@ -28,7 +28,8 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Templates/FileItems.template b/Templates/FileItems.template
new file mode 100644
index 00000000..99d7b6a9
--- /dev/null
+++ b/Templates/FileItems.template
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/GraphicObjects/Button.cs b/src/GraphicObjects/Button.cs
index 5967d94e..d4b95457 100644
--- a/src/GraphicObjects/Button.cs
+++ b/src/GraphicObjects/Button.cs
@@ -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)
{
diff --git a/src/GraphicObjects/Expandable.cs b/src/GraphicObjects/Expandable.cs
index 2328fd5f..43f44a93 100644
--- a/src/GraphicObjects/Expandable.cs
+++ b/src/GraphicObjects/Expandable.cs
@@ -65,25 +65,6 @@ namespace Crow
{
IsExpanded = !IsExpanded;
}
- ///
- /// Implement the abstract Content property of TemplatedControl
- ///
- 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 {
diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs
index b7ca11f6..3da8330d 100644
--- a/src/GraphicObjects/GraphicObject.cs
+++ b/src/GraphicObjects/GraphicObject.cs
@@ -205,10 +205,10 @@ namespace Crow
public Rectangle LastSlots;
///
/// 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
///
+ //TODO: we should ensure the whole parsed widget tree is the last painted
public Rectangle LastPaintedSlot;
/// Prevent requeuing multiple times the same widget
public bool IsQueueForRedraw = false;
diff --git a/src/GraphicObjects/GroupBox.cs b/src/GraphicObjects/GroupBox.cs
index e5a170ae..61e7f2af 100644
--- a/src/GraphicObjects/GroupBox.cs
+++ b/src/GraphicObjects/GroupBox.cs
@@ -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
}
}
diff --git a/src/GraphicObjects/Popper.cs b/src/GraphicObjects/Popper.cs
index 175c99fd..9f60aa40 100644
--- a/src/GraphicObjects/Popper.cs
+++ b/src/GraphicObjects/Popper.cs
@@ -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);
}
diff --git a/src/GraphicObjects/TabItem.cs b/src/GraphicObjects/TabItem.cs
index 9dfff864..b19d14e8 100644
--- a/src/GraphicObjects/TabItem.cs
+++ b/src/GraphicObjects/TabItem.cs
@@ -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; }}
diff --git a/src/GraphicObjects/TemplatedContainer.cs b/src/GraphicObjects/TemplatedContainer.cs
index 02c14d38..a2e35eab 100644
--- a/src/GraphicObjects/TemplatedContainer.cs
+++ b/src/GraphicObjects/TemplatedContainer.cs
@@ -31,7 +31,12 @@ using System.Reflection;
namespace Crow
{
- public abstract class TemplatedContainer : TemplatedControl
+ ///
+ /// 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
+ ///
+ 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;}
+ ///
+ /// Single child of this templated container.
+ ///
+ 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)
diff --git a/src/GraphicObjects/TemplatedControl.cs b/src/GraphicObjects/TemplatedControl.cs
index 6e236c8d..a3a6b142 100644
--- a/src/GraphicObjects/TemplatedControl.cs
+++ b/src/GraphicObjects/TemplatedControl.cs
@@ -54,6 +54,7 @@ namespace Crow
///
/// Template path
///
+ //TODO: this property should be renamed 'TemplatePath'
[XmlAttributeAttribute][DefaultValue(null)]
public string Template {
get { return _template; }
@@ -69,7 +70,7 @@ namespace Crow
}
}
///
- /// caption property being recurrent in templated widget, it is declared here.
+ /// a caption being recurrent need in templated widget, it is declared here.
///
[XmlAttributeAttribute()][DefaultValue("Templated Control")]
public virtual string Caption {
diff --git a/src/GraphicObjects/TemplatedGroup.cs b/src/GraphicObjects/TemplatedGroup.cs
index aaeb77f6..81ea25fb 100644
--- a/src/GraphicObjects/TemplatedGroup.cs
+++ b/src/GraphicObjects/TemplatedGroup.cs
@@ -67,7 +67,11 @@ namespace Crow
public Dictionary ItemTemplates = new Dictionary();
///
- /// 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
///
[XmlAttributeAttribute][DefaultValue("#Crow.Templates.ItemTemplate.goml")]
public string ItemTemplate {
@@ -272,10 +276,8 @@ namespace Crow
/// Items loading thread
///
void loading(){
- if (ItemTemplates == null)
- ItemTemplates = new Dictionary ();
- 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) {
diff --git a/src/GraphicObjects/Window.cs b/src/GraphicObjects/Window.cs
index d1f34374..efc8f4e3 100644
--- a/src/GraphicObjects/Window.cs
+++ b/src/GraphicObjects/Window.cs
@@ -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);
diff --git a/src/Instantiator.cs b/src/Instantiator.cs
index 902092e2..5f187c58 100644
--- a/src/Instantiator.cs
+++ b/src/Instantiator.cs
@@ -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
}
+ ///
+ /// Initializes a new instance of the Instantiator class with an already openned xml reader
+ /// positionned on the start tag inside the itemTemplate
+ ///
+ public Instantiator (XmlReader itr){
+ parseIML (itr);
+ }
//TODO:check if still used
public Instantiator (Type _root, InstanciatorInvoker _loader)
{
@@ -144,7 +152,7 @@ namespace Crow.IML
///
/// Parses IML and build a dynamic method that will be used to instanciate one or multiple occurence of the IML file or fragment
///
- 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
///
- 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)
+ ///
+ /// main parsing entry point
+ ///
+ void emitLoader (XmlReader reader, IMLContext ctx)
{
string tmpXml = reader.ReadOuterXml ();
@@ -195,6 +203,41 @@ namespace Crow.IML
//emitCheckAndBindValueChanged (ctx);
}
///
+ /// Parses the item template tag.
+ ///
+ /// the string triplet dataType, itemTmpID read as attribute of this tag
+ /// current xml text reader
+ /// /// file containing the templates if its a dedicated one
+ string[] parseItemTemplateTag (XmlReader reader, string itemTemplatePath = "") {
+ 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 };
+ }
+ ///
/// process template and item template definition prior to
/// other attributes or childs processing
///
@@ -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
diff --git a/src/ItemTemplate.cs b/src/ItemTemplate.cs
index d866bc19..d0c6873e 100644
--- a/src/ItemTemplate.cs
+++ b/src/ItemTemplate.cs
@@ -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){