]> 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)
25 files changed:
Crow.Test/Crow.Test.csproj
Crow.csproj
CrowIDE/CrowIDE.csproj
CrowIDE/OpenGL/Extensions.cs [new file with mode: 0644]
CrowIDE/OpenTKGameWindow.cs [deleted file]
CrowIDE/src/CrowIDE.cs
CrowIDE/src/CrowWindow.cs [new file with mode: 0644]
CrowIDE/src/Extensions.cs
CrowIDE/src/ImlVisualEditor.cs
CrowIDE/src/InterfaceControler.cs [new file with mode: 0644]
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 90cd929099bb714860cb76b8d6eadec7fba5c374..c2a44269824d9f382bbe8250605e6f6d212db0b0 100644 (file)
     <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
     <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
+    <StartAction>Program</StartAction>
+    <StartProgram>%24{TargetName}</StartProgram>
+    <StartWorkingDirectory>%24{SolutionDir}\build\%24{ProjectConfigName}</StartWorkingDirectory>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Data" />
@@ -47,7 +53,6 @@
     <Reference Include="System.Drawing" />
     <Reference Include="OpenTK">
       <HintPath>$(SolutionDir)packages\OpenTK.2.0.0\lib\net20\OpenTK.dll</HintPath>
-      <Package>opentk</Package>
     </Reference>
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
@@ -58,7 +63,6 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="OpenTKGameWindow.cs" />
     <Compile Include="OpenGL\Shader.cs" />
     <Compile Include="OpenGL\Texture.cs" />
     <Compile Include="OpenGL\vaoMesh.cs" />
@@ -67,6 +71,9 @@
     <Compile Include="src\MembersView.cs" />
     <Compile Include="src\Extensions.cs" />
     <Compile Include="src\Microsoft.Build.CommonTypes.cs" />
+    <Compile Include="src\CrowWindow.cs" />
+    <Compile Include="src\InterfaceControler.cs" />
+    <Compile Include="OpenGL\Extensions.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="ui\" />
diff --git a/CrowIDE/OpenGL/Extensions.cs b/CrowIDE/OpenGL/Extensions.cs
new file mode 100644 (file)
index 0000000..7b26f76
--- /dev/null
@@ -0,0 +1,41 @@
+//
+//  Extensions.cs
+//
+//  Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+//  Copyright (c) 2017 jp
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+using System;
+using OpenTK;
+using Crow;
+
+namespace Crow
+{
+       public static partial class Extensions {
+               public static Vector4 ToVector4(this Color c){
+                       float[] f = c.floatArray;
+                       return new Vector4 (f [0], f [1], f [2], f [3]);
+               }
+               public static Vector3 Transform(this Vector3 v, Matrix4 m){
+                       return Vector4.Transform(new Vector4(v, 1), m).Xyz;
+               }
+               public static bool IsInBetween(this int v, int min, int max){
+                       return v >= min & v <= max;
+               }
+
+       }
+}
+
diff --git a/CrowIDE/OpenTKGameWindow.cs b/CrowIDE/OpenTKGameWindow.cs
deleted file mode 100644 (file)
index b385190..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-//
-//  OpenTKGameWindow.cs
-//
-//  Author:
-//       Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-//  Copyright (c) 2016 jp
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-using System;
-using System.Threading;
-using OpenTK;
-using OpenTK.Graphics.OpenGL;
-
-namespace Crow
-{
-       public class OpenTKGameWindow : GameWindow, IValueChange
-    {
-               #region IValueChange implementation
-               public event EventHandler<ValueChangeEventArgs> ValueChanged;
-               public virtual void NotifyValueChanged(string MemberName, object _value)
-               {
-                       if (ValueChanged != null)
-                               ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value));
-               }
-               #endregion
-
-               public Interface CrowInterface;
-
-               #region FPS
-               int frameCpt = 0;
-               int _fps = 0;
-
-               public int fps {
-                       get { return _fps; }
-                       set {
-                               if (_fps == value)
-                                       return;
-
-                               _fps = value;
-
-                               if (_fps > fpsMax) {
-                                       fpsMax = _fps;
-                                       ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMax", fpsMax));
-                               } else if (_fps < fpsMin) {
-                                       fpsMin = _fps;
-                                       ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMin", fpsMin));
-                               }
-
-                               ValueChanged.Raise(this, new ValueChangeEventArgs ("fps", _fps));
-                               #if MEASURE_TIME
-                               ValueChanged.Raise (this, new ValueChangeEventArgs ("update",
-                                       this.CrowInterface.updateTime.ElapsedTicks.ToString () + " ticks"));
-                               ValueChanged.Raise (this, new ValueChangeEventArgs ("layouting",
-                                       this.CrowInterface.layoutTime.ElapsedTicks.ToString () + " ticks"));
-                               ValueChanged.Raise (this, new ValueChangeEventArgs ("drawing",
-                                       this.CrowInterface.drawingTime.ElapsedTicks.ToString () + " ticks"));
-                               ValueChanged.Raise (this, new ValueChangeEventArgs ("clipping",
-                                       this.CrowInterface.clippingTime.ElapsedTicks.ToString () + " ticks"));
-                               #endif
-                       }
-               }
-
-               public int fpsMin = int.MaxValue;
-               public int fpsMax = 0;
-
-               void resetFps ()
-               {
-                       fpsMin = int.MaxValue;
-                       fpsMax = 0;
-                       _fps = 0;
-               }
-               public string update = "";
-               public string drawing = "";
-               public string layouting = "";
-               public string clipping = "";
-               #endregion
-
-               #region ctor
-               public OpenTKGameWindow(int _width = 800, int _height = 600, string _title="Crow",
-                       int colors = 32, int depth = 24, int stencil = 0, int samples = 1,
-                       int major=3, int minor=3)
-                       : this(_width, _height, new OpenTK.Graphics.GraphicsMode(colors, depth, stencil, samples),
-                               _title,GameWindowFlags.Default,DisplayDevice.Default,
-                               major,minor,OpenTK.Graphics.GraphicsContextFlags.Default)
-               {
-               }
-               public OpenTKGameWindow (int width, int height, OpenTK.Graphics.GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags)
-                       : base(width,height,mode,title,options,device,major,minor,flags)
-               {
-                       CrowInterface = new Interface ();
-
-                       Thread t = new Thread (interfaceThread);
-                       t.IsBackground = true;
-                       t.Start ();
-               }
-
-               #endregion
-
-               void interfaceThread()
-               {
-                       CrowInterface.Quit += Quit;
-                       CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
-                       while (CrowInterface.ClientRectangle.Size.Width == 0)
-                               Thread.Sleep (5);
-
-                       while (true) {
-                               CrowInterface.Update ();
-                               Thread.Sleep (1);
-                       }
-               }
-
-               public void Quit (object sender, EventArgs e)
-               {
-                       this.Exit ();
-               }
-               void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
-               {
-                       this.Cursor = new MouseCursor(
-                               (int)e.NewCursor.Xhot,
-                               (int)e.NewCursor.Yhot,
-                               (int)e.NewCursor.Width,
-                               (int)e.NewCursor.Height,
-                               e.NewCursor.data);
-               }
-
-               #region Events
-               //those events are raised only if mouse isn't in a graphic object
-               public event EventHandler<OpenTK.Input.MouseWheelEventArgs> MouseWheelChanged;
-               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseButtonUp;
-               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseButtonDown;
-               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> MouseClick;
-               public event EventHandler<OpenTK.Input.MouseMoveEventArgs> MouseMove;
-               public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyboardKeyDown;
-               public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> KeyboardKeyUp;
-
-               #endregion
-
-               #region graphic context
-               public int texID;
-               public Shader shader;
-               public vaoMesh quad;
-               public Matrix4 projection;
-
-               void createContext()
-               {
-                       #region Create texture
-                       if (GL.IsTexture(texID))
-                               GL.DeleteTexture (texID);
-                       GL.GenTextures(1, out texID);
-                       GL.ActiveTexture (TextureUnit.Texture0);
-                       GL.BindTexture(TextureTarget.Texture2D, texID);
-
-                       GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
-                               ClientRectangle.Width, ClientRectangle.Height, 0,
-                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp);
-
-                       GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
-                       GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
-
-                       GL.BindTexture(TextureTarget.Texture2D, 0);
-                       #endregion
-               }
-               void OpenGLDraw()
-               {
-                       bool blend, depthTest;
-                       GL.GetBoolean (GetPName.Blend, out blend);
-                       GL.GetBoolean (GetPName.DepthTest, out depthTest);
-                       GL.Enable (EnableCap.Blend);
-                       GL.Disable (EnableCap.DepthTest);
-
-                       shader.Enable ();
-                       shader.SetMVP (projection);
-                       GL.ActiveTexture (TextureUnit.Texture0);
-                       GL.BindTexture (TextureTarget.Texture2D, texID);
-                       lock (CrowInterface.RenderMutex) {
-                               if (CrowInterface.IsDirty) {
-                                       GL.TexSubImage2D (TextureTarget.Texture2D, 0,
-                                               CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top,
-                                               CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height,
-                                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.dirtyBmp);
-                                       CrowInterface.IsDirty = false;
-                               }
-                       }
-                       quad.Render (BeginMode.TriangleStrip);
-                       GL.BindTexture(TextureTarget.Texture2D, 0);
-
-                       if (!blend)
-                               GL.Disable (EnableCap.Blend);
-                       if (depthTest)
-                               GL.Enable (EnableCap.DepthTest);
-               }
-               #endregion
-
-               /// <summary>
-               /// Override this method for your OpenGL rendering calls
-               /// </summary>
-               public virtual void OnRender(FrameEventArgs e)
-               {
-               }
-               /// <summary>
-               /// Override this method to customize clear method between frames
-               /// </summary>
-               public virtual void GLClear()
-               {
-                       GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
-               }
-
-               #region Game win overrides
-               protected override void OnLoad(EventArgs e)
-               {
-                       base.OnLoad(e);
-
-                       this.KeyPress += new EventHandler<OpenTK.KeyPressEventArgs>(OpenTKGameWindow_KeyPress);
-                       Keyboard.KeyDown += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyDown);
-                       Keyboard.KeyUp += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyUp);
-                       Mouse.WheelChanged += new EventHandler<OpenTK.Input.MouseWheelEventArgs>(Mouse_WheelChanged);
-                       Mouse.ButtonDown += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(Mouse_ButtonDown);
-                       Mouse.ButtonUp += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(Mouse_ButtonUp);
-                       Mouse.Move += new EventHandler<OpenTK.Input.MouseMoveEventArgs>(Mouse_Move);
-
-                       GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-                       Console.WriteLine("\n\n*************************************");
-                       Console.WriteLine("GL version: " + GL.GetString (StringName.Version));
-                       Console.WriteLine("GL vendor: " + GL.GetString (StringName.Vendor));
-                       Console.WriteLine("GLSL version: " + GL.GetString (StringName.ShadingLanguageVersion));
-                       Console.WriteLine("*************************************\n");
-
-                       projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1);
-
-                       shader = new Shader ();
-                       quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1);
-               }
-
-               protected override void OnUpdateFrame(FrameEventArgs e)
-               {
-                       base.OnUpdateFrame(e);
-                       fps = (int)RenderFrequency;
-
-
-                       if (frameCpt > 50) {
-                               resetFps ();
-                               frameCpt = 0;
-                               GC.Collect();
-                               GC.WaitForPendingFinalizers();
-                               NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString());
-                       }
-                       frameCpt++;
-               }
-               protected override void OnRenderFrame(FrameEventArgs e)
-               {
-                       GLClear ();
-
-                       base.OnRenderFrame(e);
-
-                       OnRender (e);
-                       OpenGLDraw ();
-
-                       SwapBuffers ();
-               }
-
-               protected override void OnResize(EventArgs e)
-               {
-                       base.OnResize (e);
-                       CrowInterface.ProcessResize(
-                               new Rectangle(
-                               0,
-                               0,
-                               this.ClientRectangle.Width,
-                               this.ClientRectangle.Height));
-                       createContext ();
-                       GL.Viewport (0, 0, ClientRectangle.Width, ClientRectangle.Height);
-               }
-               #endregion
-
-               #region Mouse Handling
-               void update_mouseButtonStates(ref MouseState e, OpenTK.Input.MouseState otk_e){
-                       for (int i = 0; i < MouseState.MaxButtons; i++) {
-                               if (otk_e.IsButtonDown ((OpenTK.Input.MouseButton)i))
-                                       e.EnableBit (i);
-                       }
-               }
-               void Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e)
-       {
-                       if (!CrowInterface.ProcessMouseMove (otk_e.X, otk_e.Y))
-                               MouseMove.Raise (sender, otk_e);
-       }
-               void Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
-       {
-                       if (!CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button))
-                               MouseButtonUp.Raise (sender, otk_e);
-       }
-               void Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
-               {
-                       if (!CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button))
-                               MouseButtonDown.Raise (sender, otk_e);
-       }
-               void Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e)
-       {
-                       if (!CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise))
-                               MouseWheelChanged.Raise (sender, otk_e);
-       }
-               #endregion
-
-               #region keyboard Handling
-               void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
-               {
-                       if (!CrowInterface.ProcessKeyDown((int)otk_e.Key))
-                               KeyboardKeyDown.Raise (this, otk_e);
-       }
-               void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
-               {
-                       if (!CrowInterface.ProcessKeyUp((int)otk_e.Key))
-                               KeyboardKeyUp.Raise (this, otk_e);
-               }
-               void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e)
-               {
-                       CrowInterface.ProcessKeyPress (e.KeyChar);
-               }
-       #endregion
-    }
-}
index 4c55760303bf14b671eca1655e2a51764ac32d9b..de082acc0e742a8669942d082fb488a4437ae62e 100644 (file)
@@ -31,7 +31,7 @@ using System.IO;
 
 namespace CrowIDE
 {
-       class CrowIDE : OpenTKGameWindow
+       class CrowIDE : CrowWindow
        {
                public Command CMDLoad = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Open"))) { Caption = "Open", Icon = new SvgPicture("#Crow.Icons.open-file.svg")};
                public Command CMDSave = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Save"))) { Caption = "Save", Icon = new SvgPicture("#Crow.Icons.open-file.svg")};
@@ -72,7 +72,7 @@ namespace CrowIDE
 
                        //this.CrowInterface.LoadInterface ("#CrowIDE.ui.imlEditor.crow").DataSource = this;
                        //GraphicObject go = this.CrowInterface.LoadInterface (@"ui/test.crow");
-                       GraphicObject go = this.CrowInterface.LoadInterface (@"#CrowIDE.ui.imlEditor.crow");
+                       GraphicObject go = CurrentInterface.LoadInterface (@"#CrowIDE.ui.imlEditor.crow");
                        imlVE = go.FindByName ("crowContainer") as ImlVisualEditor;
                        go.DataSource = this;
                }
@@ -94,10 +94,10 @@ namespace CrowIDE
                }
                void loadWindow(string path){
                        try {
-                               GraphicObject g = CrowInterface.FindByName (path);
+                               GraphicObject g = CurrentInterface.FindByName (path);
                                if (g != null)
                                        return;
-                               g = CrowInterface.LoadInterface (path);
+                               g = CurrentInterface.LoadInterface (path);
                                g.Name = path;
                                g.DataSource = imlVE;
                        } catch (Exception ex) {
@@ -105,9 +105,9 @@ namespace CrowIDE
                        }
                }
                void closeWindow (string path){
-                       GraphicObject g = CrowInterface.FindByName (path);
+                       GraphicObject g = CurrentInterface.FindByName (path);
                        if (g != null)
-                               CrowInterface.DeleteWidget (g);
+                               CurrentInterface.DeleteWidget (g);
                }
 
                protected void onCommandSave(object sender, MouseButtonEventArgs e){
diff --git a/CrowIDE/src/CrowWindow.cs b/CrowIDE/src/CrowWindow.cs
new file mode 100644 (file)
index 0000000..d4447a1
--- /dev/null
@@ -0,0 +1,413 @@
+//
+// CrowWindow.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using System.Collections.Generic;
+
+namespace Crow
+{
+       public class CrowWindow : GameWindow, IValueChange
+    {
+               #region IValueChange implementation
+               public event EventHandler<ValueChangeEventArgs> ValueChanged;
+               public virtual void NotifyValueChanged(string MemberName, object _value)
+               {
+                       if (ValueChanged != null)
+                               ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value));
+               }
+               #endregion
+
+               #region FPS
+               int frameCpt = 0;
+               int _fps = 0;
+
+               public int fps {
+                       get { return _fps; }
+                       set {
+                               if (_fps == value)
+                                       return;
+
+                               _fps = value;
+                               #if MEASURE_TIME
+                               if (_fps > fpsMax) {
+                                       fpsMax = _fps;
+                                       ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMax", fpsMax));
+                               } else if (_fps < fpsMin) {
+                                       fpsMin = _fps;
+                                       ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMin", fpsMin));
+                               }
+                               #endif
+                               if (frameCpt % 3 == 0) {
+                                       ValueChanged.Raise (this, new ValueChangeEventArgs ("fps", _fps));
+                                       #if MEASURE_TIME
+                                       foreach (PerformanceMeasure m in ifaceControl[0].PerfMeasures)
+                                               m.NotifyChanges ();
+                                       #endif
+                               }
+                       }
+               }
+
+               #if MEASURE_TIME
+               public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
+
+               public int fpsMin = int.MaxValue;
+               public int fpsMax = 0;
+
+               void resetFps ()
+               {
+                       fpsMin = int.MaxValue;
+                       fpsMax = 0;
+                       _fps = 0;
+               }
+               #endif
+
+               #endregion
+
+               #region ctor
+               public CrowWindow(int _width = 800, int _height = 600, string _title="Crow",
+                       int colors = 32, int depth = 24, int stencil = 0, int samples = 1,
+                       int major=3, int minor=3)
+                       : this(_width, _height, new OpenTK.Graphics.GraphicsMode(colors, depth, stencil, samples),
+                               _title,GameWindowFlags.Default,DisplayDevice.Default,
+                               major,minor,OpenTK.Graphics.GraphicsContextFlags.Default)
+               {
+               }
+               public CrowWindow (int width, int height, OpenTK.Graphics.GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags)
+                       : base(width,height,mode,title,options,device,major,minor,flags)
+               {
+               }
+
+               #endregion
+
+               protected Shader shader;
+               public List<InterfaceControler> ifaceControl = new List<InterfaceControler>();
+               int focusedIdx = -1, activeIdx = -2;
+
+               // TODO:We should be able to set the current interface programmaticaly
+               /// <summary>
+               /// Gets the currently focused interface, focus could have been given by creation of new iface controler and
+               /// not only by the mouse
+               /// </summary>
+               public Interface CurrentInterface {
+                       get {
+                               if (ifaceControl.Count == 0) {//create default orthogonal interface
+                                       addInterfaceControler (new InterfaceControler (
+                                               new Rectangle (0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height)));
+                                       focusedIdx = 0;
+                               }
+                               return ifaceControl [focusedIdx].CrowInterface;
+                       }
+               }
+                       
+               void addInterfaceControler(InterfaceControler ifaceControler)
+               {
+                       ifaceControler.CrowInterface.Quit += Quit;
+                       ifaceControler.CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
+
+                       ifaceControl.Add (ifaceControler);
+                       focusedIdx = ifaceControl.Count - 1;
+               }
+               void openGLDraw(){
+                       //save GL states
+                       bool blend, depthTest, cullFace;
+                       GL.GetBoolean (GetPName.Blend, out blend);
+                       GL.GetBoolean (GetPName.DepthTest, out depthTest);
+                       GL.GetBoolean (GetPName.CullFace, out cullFace);
+                       GL.Enable (EnableCap.Blend);
+                       GL.Disable (EnableCap.DepthTest);
+                       GL.Disable (EnableCap.CullFace);
+
+                       #if MEASURE_TIME
+                       glDrawMeasure.StartCycle();
+                       #endif
+
+                       shader.Enable ();
+                       for (int i = 0; i < ifaceControl.Count; i++) {
+                               shader.SetMVP (ifaceControl [i].InterfaceMVP);
+                               ifaceControl [i].OpenGLDraw ();
+                       }
+
+                       #if MEASURE_TIME
+                       glDrawMeasure.StopCycle();
+                       #endif
+
+                       //restore GL states
+                       if (!blend)
+                               GL.Disable (EnableCap.Blend);
+                       if (depthTest)
+                               GL.Enable (EnableCap.DepthTest);
+                       if (cullFace)
+                               GL.Enable (EnableCap.CullFace);
+               }
+
+               public void Quit (object sender, EventArgs e)
+               {
+                       foreach (InterfaceControler ic in ifaceControl) {
+                               ic.Dispose ();
+                       }
+                       this.Exit ();
+               }
+               void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
+               {
+                       this.Cursor = new MouseCursor(
+                               (int)e.NewCursor.Xhot,
+                               (int)e.NewCursor.Yhot,
+                               (int)e.NewCursor.Width,
+                               (int)e.NewCursor.Height,
+                               e.NewCursor.data);
+               }
+
+               #region Events
+               //those events are raised only if mouse isn't in a graphic object
+               public event EventHandler<OpenTK.Input.MouseWheelEventArgs> CrowMouseWheel;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> CrowMouseUp;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> CrowMouseDown;
+               public event EventHandler<OpenTK.Input.MouseButtonEventArgs> CrowMouseClick;
+               public event EventHandler<OpenTK.Input.MouseMoveEventArgs> CrowMouseMove;
+               public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> CrowKeyDown;
+               public event EventHandler<OpenTK.Input.KeyboardKeyEventArgs> CrowKeyUp;
+
+               #endregion
+
+               public ProjectiveIFaceControler Add3DInterface(int width, int height, Matrix4 ifaceModelMat){
+                       ProjectiveIFaceControler tmp = new ProjectiveIFaceControler (new Rectangle (0, 0, width, height), ifaceModelMat);
+                       addInterfaceControler (tmp);
+                       return tmp;
+               }
+               public GraphicObject AddWidget (GraphicObject g, int interfaceIdx = 0){
+                       if (ifaceControl.Count == 0)//create default orthogonal interface
+                               addInterfaceControler (new InterfaceControler (
+                                       new Rectangle (0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height)));
+                       ifaceControl [interfaceIdx].CrowInterface.AddWidget (g);
+                       return g;
+               }
+
+               public void DeleteWidget (GraphicObject g, int interfaceIdx = 0){
+                       ifaceControl [interfaceIdx].CrowInterface.DeleteWidget (g);
+               }
+               /// <summary>
+               /// check if a default interface exists, create one if not
+               /// </summary>
+               void checkDefaultIFace (){
+                       if (ifaceControl.Count == 0)//create default orthogonal interface
+                               addInterfaceControler (new InterfaceControler (
+                                       new Rectangle (0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height)));                        
+               }
+               /// <summary>
+               /// Load the content of the IML file pointed by path and add it to the current interface
+               /// graphic tree.
+               /// </summary>
+               /// <param name="path">the path of the IML file to load</param>
+               /// <param name="interfaceIdx">interface index to bind to, a default one is created if none exists</param>
+               public GraphicObject Load (string path, int interfaceIdx = 0){
+                       checkDefaultIFace();
+                       return ifaceControl [interfaceIdx].CrowInterface.LoadInterface (path);
+               }
+               /// <summary>
+               /// Load the content of the IML string passed as first argument and add it to the current interface
+               /// graphic tree.
+               /// </summary>
+               /// <param name="path">a valid IML string</param>
+               /// <param name="interfaceIdx">interface index to bind to, a default one is created if none exists</param>
+               public void LoadIMLFragment (string imlFragment, int interfaceIdx = 0){
+                       checkDefaultIFace();
+                       ifaceControl [interfaceIdx].CrowInterface.LoadIMLFragment (imlFragment);
+               }
+
+               public GraphicObject FindByName (string nameToFind){
+                       for (int i = 0; i < ifaceControl.Count; i++) {
+                               GraphicObject tmp = ifaceControl [i].CrowInterface.FindByName (nameToFind);
+                               if (tmp != null)
+                                       return tmp;
+                       }
+                       return null;
+               }
+               public void ClearInterface (int interfaceIdx = 0){
+                       ifaceControl [interfaceIdx].CrowInterface.ClearInterface ();
+               }
+               /// <summary>Override this method for your OpenGL rendering calls</summary>
+               public virtual void OnRender(FrameEventArgs e)
+               {
+               }
+               /// <summary>Override this method to customize clear method between frames</summary>
+               public virtual void GLClear()
+               {
+                       GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
+               }
+
+               #region Game win overrides
+               protected override void OnLoad(EventArgs e)
+               {
+                       base.OnLoad(e);
+
+                       this.KeyPress += new EventHandler<OpenTK.KeyPressEventArgs>(OpenTKGameWindow_KeyPress);
+                       KeyDown += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyDown);
+                       KeyUp += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyUp);
+
+                       MouseWheel += new EventHandler<OpenTK.Input.MouseWheelEventArgs>(GL_Mouse_WheelChanged);
+                       MouseDown += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(GL_Mouse_ButtonDown);
+                       MouseUp += new EventHandler<OpenTK.Input.MouseButtonEventArgs>(GL_Mouse_ButtonUp);
+                       MouseMove += new EventHandler<OpenTK.Input.MouseMoveEventArgs>(GL_Mouse_Move);
+
+                       #if DEBUG
+                       Console.WriteLine("\n\n*************************************");
+                       Console.WriteLine("GL version: " + GL.GetString (StringName.Version));
+                       Console.WriteLine("GL vendor: " + GL.GetString (StringName.Vendor));
+                       Console.WriteLine("GLSL version: " + GL.GetString (StringName.ShadingLanguageVersion));
+                       Console.WriteLine("*************************************\n");
+                       #endif
+
+                       shader = new Shader ();
+                       shader.Enable ();
+
+                       GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+               }
+               protected override void OnUpdateFrame(FrameEventArgs e)
+               {
+                       base.OnUpdateFrame(e);
+                       fps = (int)RenderFrequency;
+
+                       #if MEASURE_TIME
+                       if (frameCpt > 500) {
+                               resetFps ();
+                               frameCpt = 0;
+//                             #if DEBUG
+//                             GC.Collect();
+//                             GC.WaitForPendingFinalizers();
+//                             NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString());
+//                             #endif
+                       }
+                       #endif
+
+                       frameCpt++;
+               }
+               protected override void OnRenderFrame(FrameEventArgs e)
+               {
+                       GLClear ();
+
+                       base.OnRenderFrame(e);
+
+                       OnRender (e);
+                       openGLDraw ();
+
+
+                       SwapBuffers ();
+               }
+               protected override void OnResize(EventArgs e)
+               {
+                       base.OnResize (e);
+                       for (int i = 0; i < ifaceControl.Count; i++) {
+                               ifaceControl[i].ProcessResize(
+                                       new Rectangle(
+                                               0,
+                                               0,
+                                               this.ClientRectangle.Width,
+                                               this.ClientRectangle.Height));
+                       }
+               }
+               #endregion
+
+               #region Mouse and Keyboard Handling
+               void update_mouseButtonStates(ref MouseState e, OpenTK.Input.MouseState otk_e){
+                       for (int i = 0; i < MouseState.MaxButtons; i++) {
+                               if (otk_e.IsButtonDown ((OpenTK.Input.MouseButton)i))
+                                       e.EnableBit (i);
+                       }
+               }
+               protected virtual void GL_Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e)
+        {
+                       if (activeIdx == -2) {
+                               focusedIdx = -1;
+                               for (int i = 0; i < ifaceControl.Count; i++) {
+                                       if (ifaceControl [i].ProcessMouseMove (otk_e.X, otk_e.Y)) {
+                                               focusedIdx = i;
+                                               return;
+                                       }
+                               }
+                       } else if (focusedIdx >= 0) {
+                               ifaceControl [focusedIdx].ProcessMouseMove (otk_e.X, otk_e.Y);
+                               return;
+                       }
+                       if (focusedIdx < 0)
+                               CrowMouseMove.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
+        {
+                       activeIdx = -2;
+                       if (focusedIdx >= 0) {
+                               if (ifaceControl [focusedIdx].ProcessMouseButtonUp ((int)otk_e.Button))
+                                       return;
+                       }
+                       CrowMouseUp.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e)
+               {
+                       activeIdx = focusedIdx;
+                       if (focusedIdx >= 0) {
+                               if (ifaceControl [focusedIdx].ProcessMouseButtonDown ((int)otk_e.Button))
+                                       return;
+                       }
+                       CrowMouseDown.Raise (sender, otk_e);
+        }
+               protected virtual void GL_Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e)
+        {
+                       if (focusedIdx >= 0) {
+                               if (ifaceControl [focusedIdx].ProcessMouseWheelChanged (otk_e.DeltaPrecise))
+                                       return;
+                       }
+                       CrowMouseWheel.Raise (sender, otk_e);
+        }
+
+               protected virtual void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
+               {
+                       if (focusedIdx >= 0) {
+                               if (ifaceControl [focusedIdx].ProcessKeyDown((int)otk_e.Key))
+                                       return;
+                       }
+                       CrowKeyDown.Raise (this, otk_e);
+        }
+               protected virtual void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e)
+               {
+                       if (focusedIdx >= 0) {
+                               if (ifaceControl [focusedIdx].ProcessKeyUp((int)otk_e.Key))
+                                       return;
+                       }
+                       CrowKeyUp.Raise (this, otk_e);
+               }
+               protected virtual void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e)
+               {
+                       if (focusedIdx >= 0) {
+                               if (ifaceControl [focusedIdx].ProcessKeyPress (e.KeyChar))
+                                       return;
+                       }
+                       //TODO:create keyboardkeypress evt
+               }
+        #endregion
+    }
+}
index 5e8981dfeb00075417871062775a3e33f1173dea..0d12fec8d514007ce00965db7c4ace97f00293b8 100644 (file)
@@ -23,7 +23,7 @@ using System.Collections.Generic;
 
 namespace Crow
 {
-       public static class Extensions
+       public static partial class Extensions
        {
                public static List<GraphicObject> GetChildren(this GraphicObject go){
                        Type goType = go.GetType();
index 61a1e8c8326a5e03e0e32f54be6652c463f699c2..49a20a641d4639f2793b9ab8fadb0bf5f039ef00 100644 (file)
@@ -25,6 +25,7 @@ using System.Xml.Serialization;
 using System.ComponentModel;
 using System.IO;
 using System.Collections.Generic;
+using Crow.IML;
 
 namespace CrowIDE
 {
diff --git a/CrowIDE/src/InterfaceControler.cs b/CrowIDE/src/InterfaceControler.cs
new file mode 100644 (file)
index 0000000..5098e11
--- /dev/null
@@ -0,0 +1,267 @@
+//
+// InterfaceControler.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using System.Threading;
+using System.Collections.Generic;
+
+namespace Crow
+{
+       public class ProjectiveIFaceControler : InterfaceControler {
+               Matrix4 modelview;
+               int[] viewport = new int[4];
+               Vector3 vEyePosition;
+
+               public Matrix4 ifaceModelMat;
+               Point localMousePos;
+
+               public ProjectiveIFaceControler(Rectangle ifaceBounds, Matrix4 _ifaceModelMat)
+                       : base(ifaceBounds){
+                       ifaceModelMat = _ifaceModelMat;
+               }
+
+               public override Matrix4 InterfaceMVP {
+                       get { return ifaceModelMat * modelview * projection; }
+               }
+
+               public override void initGL(){
+                       quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1);
+                       //ifaceModelMat = Matrix4.CreateRotationX(MathHelper.PiOver2) * Matrix4.CreateTranslation(Vector3.UnitY);
+                       CrowInterface.ProcessResize(iRect);
+                       createContext ();
+                       //CrowInterface.ProcessResize (iRect);
+               }
+               public override void ProcessResize (Rectangle newSize)
+               {
+               }
+               public override void OpenGLDraw ()
+               {
+                       GL.Enable (EnableCap.DepthTest);
+                       base.OpenGLDraw ();
+                       GL.Disable (EnableCap.DepthTest);
+               }
+               public void UpdateView (Matrix4 _projection, Matrix4 _modelview, int[] _viewport, Vector3 _vEyePosition)
+               {
+                       projection = _projection;
+                       modelview = _modelview;
+                       viewport = _viewport;
+                       vEyePosition = _vEyePosition;
+               }
+               public override bool ProcessMouseMove (int x, int y)
+               {
+                       Matrix4 mv = ifaceModelMat * modelview;
+                       Vector3 vMouse = UnProject(ref projection, ref mv, viewport, new Vector2 (x, y)).Xyz;
+                       Vector3 vE = vEyePosition.Transform (ifaceModelMat.Inverted());
+                       Vector3 vMouseRay = Vector3.Normalize(vMouse - vE);
+                       float a = vE.Z / vMouseRay.Z;
+                       vMouse = vE - vMouseRay * a;
+                       //vMouse = vMouse.Transform (interfaceModelView.Inverted());
+                       localMousePos = new Point ((int)Math.Truncate ((vMouse.X + 0.5f) * iRect.Width),
+                               iRect.Height - (int)Math.Truncate ((vMouse.Y + 0.5f) * iRect.Height));
+                       mouseIsInInterface = localMousePos.X.IsInBetween (0, iRect.Width) & localMousePos.Y.IsInBetween (0, iRect.Height);
+
+                       return mouseIsInInterface ? CrowInterface.ProcessMouseMove (localMousePos.X, localMousePos.Y) : false;
+               }
+               Vector4 UnProject(ref Matrix4 projection, ref Matrix4 view, int[] viewport, Vector2 mouse)
+               {
+                       Vector4 vec;
+
+                       vec.X = 2.0f * mouse.X / (float)viewport[2] - 1;
+                       vec.Y = -(2.0f * mouse.Y / (float)viewport[3] - 1);
+                       vec.Z = 0f;
+                       vec.W = 1.0f;
+
+                       Matrix4 viewInv = Matrix4.Invert(view);
+                       Matrix4 projInv = Matrix4.Invert(projection);
+
+                       Vector4.Transform(ref vec, ref projInv, out vec);
+                       Vector4.Transform(ref vec, ref viewInv, out vec);
+
+                       if (vec.W > float.Epsilon || vec.W < float.Epsilon)
+                       {
+                               vec.X /= vec.W;
+                               vec.Y /= vec.W;
+                               vec.Z /= vec.W;
+                       }
+
+                       return vec;
+               }
+       }
+       public class InterfaceControler : IDisposable {
+               public Interface CrowInterface;
+               public int texID;
+               public vaoMesh quad;
+               public Rectangle iRect = new Rectangle(0,0,2048,2048);
+               public bool mouseIsInInterface = false;
+
+               protected Matrix4 projection;
+               public virtual Matrix4 InterfaceMVP {
+                       get { return projection; }
+               }
+
+               #if MEASURE_TIME
+               public List<PerformanceMeasure> PerfMeasures;
+               public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
+               #endif
+
+               #region CTOR
+               public InterfaceControler(Rectangle ifaceBounds){
+                       iRect = ifaceBounds;
+
+                       CrowInterface = new Interface ();
+
+                       #if MEASURE_TIME
+                       PerfMeasures = new List<PerformanceMeasure> (
+                               new PerformanceMeasure[] {
+                                       this.CrowInterface.updateMeasure,
+                                       this.CrowInterface.layoutingMeasure,
+                                       this.CrowInterface.clippingMeasure,
+                                       this.CrowInterface.drawingMeasure,
+                                       this.glDrawMeasure
+                               }
+                       );
+                       #endif
+
+                       Thread t = new Thread (interfaceThread);
+                       t.IsBackground = true;
+                       t.Start ();
+
+                       initGL ();
+               }
+               #endregion
+
+               void interfaceThread()
+               {
+                       while (CrowInterface.ClientRectangle.Size.Width == 0)
+                               Thread.Sleep (5);
+
+                       while (true) {
+                               CrowInterface.Update ();
+                               Thread.Sleep (2);
+                       }
+               }
+
+               #region Mouse And Keyboard handling
+               public virtual void ProcessResize(Rectangle newSize){
+                       iRect = newSize;
+                       CrowInterface.ProcessResize(newSize);
+                       createContext ();
+                       GL.Viewport (0, 0, newSize.Width, newSize.Height);//TODO:find a better place for this
+               }
+               public virtual bool ProcessMouseMove(int x, int y){
+                       return CrowInterface.ProcessMouseMove (x, y);
+               }
+               public virtual bool ProcessMouseButtonUp(int button)
+               {
+                       return CrowInterface.ProcessMouseButtonUp (button);
+               }
+               public virtual bool ProcessMouseButtonDown(int button)
+               {
+                       return CrowInterface.ProcessMouseButtonDown (button);
+               }
+               public virtual bool ProcessMouseWheelChanged(float delta)
+               {
+                       return CrowInterface.ProcessMouseWheelChanged (delta);
+               }
+               public virtual bool ProcessKeyDown(int Key){
+                       return CrowInterface.ProcessKeyDown(Key);
+               }
+               public virtual bool ProcessKeyUp(int Key){
+                       return CrowInterface.ProcessKeyUp(Key);
+               }
+               public virtual bool ProcessKeyPress(char Key){
+                       return CrowInterface.ProcessKeyPress(Key);
+               }
+               #endregion
+
+               #region graphic context
+               public virtual void initGL(){
+                       projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1);
+                       quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1);
+                       createContext ();
+               }
+               /// <summary>Create the texture for the interface redering</summary>
+               public virtual void createContext()
+               {
+                       if (GL.IsTexture(texID))
+                               GL.DeleteTexture (texID);
+                       GL.GenTextures(1, out texID);
+                       GL.ActiveTexture (TextureUnit.Texture0);
+                       GL.BindTexture(TextureTarget.Texture2D, texID);
+
+                       GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
+                               iRect.Width, iRect.Height, 0,
+                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp);
+
+                       GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
+                       GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+
+                       GL.BindTexture(TextureTarget.Texture2D, 0);
+               }
+               /// <summary>Rendering of the interface</summary>
+               public virtual void OpenGLDraw()
+               {
+                       #if MEASURE_TIME
+                       glDrawMeasure.StartCycle();
+                       #endif
+
+                       GL.ActiveTexture (TextureUnit.Texture0);
+                       GL.BindTexture (TextureTarget.Texture2D, texID);
+                       if (Monitor.TryEnter(CrowInterface.RenderMutex)) {
+                               if (CrowInterface.IsDirty) {
+                                       GL.TexSubImage2D (TextureTarget.Texture2D, 0,
+                                               CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top,
+                                               CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height,
+                                               OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.dirtyBmp);
+                                       CrowInterface.IsDirty = false;
+                               }
+                               Monitor.Exit (CrowInterface.RenderMutex);
+                       }
+                       quad.Render (BeginMode.TriangleStrip);
+                       GL.BindTexture(TextureTarget.Texture2D, 0);
+
+                       #if MEASURE_TIME
+                       glDrawMeasure.StopCycle();
+                       #endif
+               }
+               #endregion
+
+               #region IDisposable implementation
+
+               public void Dispose ()
+               {
+                       if (GL.IsTexture(texID))
+                               GL.DeleteTexture (texID);
+                       if (quad != null)
+                               quad.Dispose ();
+               }
+
+               #endregion
+       }
+}
+
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){