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: 0.6.0~7
X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=41f95a2a2d9d6d5d12a47566f5b7d74a382fd406;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/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj
index 90cd9290..c2a44269 100644
--- a/CrowIDE/CrowIDE.csproj
+++ b/CrowIDE/CrowIDE.csproj
@@ -40,6 +40,12 @@
$(SolutionDir)build\obj\$(Configuration)
$(SolutionDir)build\$(Configuration)
+
+ Program
+ %24{TargetName}
+ %24{SolutionDir}\build\%24{ProjectConfigName}
+ false
+
@@ -47,7 +53,6 @@
$(SolutionDir)packages\OpenTK.2.0.0\lib\net20\OpenTK.dll
- opentk
@@ -58,7 +63,6 @@
-
@@ -67,6 +71,9 @@
+
+
+
diff --git a/CrowIDE/OpenGL/Extensions.cs b/CrowIDE/OpenGL/Extensions.cs
new file mode 100644
index 00000000..7b26f76b
--- /dev/null
+++ b/CrowIDE/OpenGL/Extensions.cs
@@ -0,0 +1,41 @@
+//
+// Extensions.cs
+//
+// Author:
+// Jean-Philippe Bruyère
+//
+// 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 .
+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
index b3851904..00000000
--- a/CrowIDE/OpenTKGameWindow.cs
+++ /dev/null
@@ -1,334 +0,0 @@
-//
-// OpenTKGameWindow.cs
-//
-// Author:
-// Jean-Philippe Bruyère
-//
-// 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 .
-using System;
-using System.Threading;
-using OpenTK;
-using OpenTK.Graphics.OpenGL;
-
-namespace Crow
-{
- public class OpenTKGameWindow : GameWindow, IValueChange
- {
- #region IValueChange implementation
- public event EventHandler 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 MouseWheelChanged;
- public event EventHandler MouseButtonUp;
- public event EventHandler MouseButtonDown;
- public event EventHandler MouseClick;
- public event EventHandler MouseMove;
- public event EventHandler KeyboardKeyDown;
- public event EventHandler 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
-
- ///
- /// Override this method for your OpenGL rendering calls
- ///
- public virtual void OnRender(FrameEventArgs e)
- {
- }
- ///
- /// Override this method to customize clear method between frames
- ///
- 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(OpenTKGameWindow_KeyPress);
- Keyboard.KeyDown += new EventHandler(Keyboard_KeyDown);
- Keyboard.KeyUp += new EventHandler(Keyboard_KeyUp);
- Mouse.WheelChanged += new EventHandler(Mouse_WheelChanged);
- Mouse.ButtonDown += new EventHandler(Mouse_ButtonDown);
- Mouse.ButtonUp += new EventHandler(Mouse_ButtonUp);
- Mouse.Move += new EventHandler(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
- }
-}
diff --git a/CrowIDE/src/CrowIDE.cs b/CrowIDE/src/CrowIDE.cs
index 4c557603..de082acc 100644
--- a/CrowIDE/src/CrowIDE.cs
+++ b/CrowIDE/src/CrowIDE.cs
@@ -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
index 00000000..d4447a1f
--- /dev/null
+++ b/CrowIDE/src/CrowWindow.cs
@@ -0,0 +1,413 @@
+//
+// CrowWindow.cs
+//
+// Author:
+// Jean-Philippe Bruyère
+//
+// 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 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 ifaceControl = new List();
+ int focusedIdx = -1, activeIdx = -2;
+
+ // TODO:We should be able to set the current interface programmaticaly
+ ///
+ /// Gets the currently focused interface, focus could have been given by creation of new iface controler and
+ /// not only by the mouse
+ ///
+ 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 CrowMouseWheel;
+ public event EventHandler CrowMouseUp;
+ public event EventHandler CrowMouseDown;
+ public event EventHandler CrowMouseClick;
+ public event EventHandler CrowMouseMove;
+ public event EventHandler CrowKeyDown;
+ public event EventHandler 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);
+ }
+ ///
+ /// check if a default interface exists, create one if not
+ ///
+ void checkDefaultIFace (){
+ if (ifaceControl.Count == 0)//create default orthogonal interface
+ addInterfaceControler (new InterfaceControler (
+ new Rectangle (0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height)));
+ }
+ ///
+ /// Load the content of the IML file pointed by path and add it to the current interface
+ /// graphic tree.
+ ///
+ /// the path of the IML file to load
+ /// interface index to bind to, a default one is created if none exists
+ public GraphicObject Load (string path, int interfaceIdx = 0){
+ checkDefaultIFace();
+ return ifaceControl [interfaceIdx].CrowInterface.LoadInterface (path);
+ }
+ ///
+ /// Load the content of the IML string passed as first argument and add it to the current interface
+ /// graphic tree.
+ ///
+ /// a valid IML string
+ /// interface index to bind to, a default one is created if none exists
+ 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 ();
+ }
+ /// Override this method for your OpenGL rendering calls
+ public virtual void OnRender(FrameEventArgs e)
+ {
+ }
+ /// Override this method to customize clear method between frames
+ 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(OpenTKGameWindow_KeyPress);
+ KeyDown += new EventHandler(Keyboard_KeyDown);
+ KeyUp += new EventHandler(Keyboard_KeyUp);
+
+ MouseWheel += new EventHandler(GL_Mouse_WheelChanged);
+ MouseDown += new EventHandler(GL_Mouse_ButtonDown);
+ MouseUp += new EventHandler(GL_Mouse_ButtonUp);
+ MouseMove += new EventHandler(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
+ }
+}
diff --git a/CrowIDE/src/Extensions.cs b/CrowIDE/src/Extensions.cs
index 5e8981df..0d12fec8 100644
--- a/CrowIDE/src/Extensions.cs
+++ b/CrowIDE/src/Extensions.cs
@@ -23,7 +23,7 @@ using System.Collections.Generic;
namespace Crow
{
- public static class Extensions
+ public static partial class Extensions
{
public static List GetChildren(this GraphicObject go){
Type goType = go.GetType();
diff --git a/CrowIDE/src/ImlVisualEditor.cs b/CrowIDE/src/ImlVisualEditor.cs
index 61a1e8c8..49a20a64 100644
--- a/CrowIDE/src/ImlVisualEditor.cs
+++ b/CrowIDE/src/ImlVisualEditor.cs
@@ -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
index 00000000..5098e119
--- /dev/null
+++ b/CrowIDE/src/InterfaceControler.cs
@@ -0,0 +1,267 @@
+//
+// InterfaceControler.cs
+//
+// Author:
+// Jean-Philippe Bruyère
+//
+// 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 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 (
+ 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 ();
+ }
+ /// Create the texture for the interface redering
+ 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);
+ }
+ /// Rendering of the interface
+ 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
+ }
+}
+
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){