]> O.S.I.I.S - jp/crow.git/commitdiff
rename GraphicObjects folder to Widgets
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 7 Oct 2019 15:20:36 +0000 (17:20 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 7 Oct 2019 15:20:36 +0000 (17:20 +0200)
118 files changed:
Crow/src/GraphicObjects/Border.cs [deleted file]
Crow/src/GraphicObjects/Button.cs [deleted file]
Crow/src/GraphicObjects/CheckBox.cs [deleted file]
Crow/src/GraphicObjects/ColorPicker.cs [deleted file]
Crow/src/GraphicObjects/ColorSelector.cs [deleted file]
Crow/src/GraphicObjects/ColorSlider.cs [deleted file]
Crow/src/GraphicObjects/ComboBox.cs [deleted file]
Crow/src/GraphicObjects/Container.cs [deleted file]
Crow/src/GraphicObjects/DataSourceChangeEventArgs.cs [deleted file]
Crow/src/GraphicObjects/DirectoryView.cs [deleted file]
Crow/src/GraphicObjects/DockStack.cs [deleted file]
Crow/src/GraphicObjects/DockWindow.cs [deleted file]
Crow/src/GraphicObjects/EnumSelector.cs [deleted file]
Crow/src/GraphicObjects/Expandable.cs [deleted file]
Crow/src/GraphicObjects/FileDialog.cs [deleted file]
Crow/src/GraphicObjects/GenericStack.cs [deleted file]
Crow/src/GraphicObjects/GraduatedSlider.cs [deleted file]
Crow/src/GraphicObjects/Grid.cs [deleted file]
Crow/src/GraphicObjects/Group.cs [deleted file]
Crow/src/GraphicObjects/GroupBox.cs [deleted file]
Crow/src/GraphicObjects/HorizontalStack.cs [deleted file]
Crow/src/GraphicObjects/HueSelector.cs [deleted file]
Crow/src/GraphicObjects/ILayoutable.cs [deleted file]
Crow/src/GraphicObjects/IMLContainer.cs [deleted file]
Crow/src/GraphicObjects/IValueChange.cs [deleted file]
Crow/src/GraphicObjects/Image.cs [deleted file]
Crow/src/GraphicObjects/Label.cs [deleted file]
Crow/src/GraphicObjects/ListBox.cs [deleted file]
Crow/src/GraphicObjects/Menu.cs [deleted file]
Crow/src/GraphicObjects/MenuItem.cs [deleted file]
Crow/src/GraphicObjects/MessageBox.cs [deleted file]
Crow/src/GraphicObjects/NumericControl.cs [deleted file]
Crow/src/GraphicObjects/Popper.cs [deleted file]
Crow/src/GraphicObjects/PrivateContainer.cs [deleted file]
Crow/src/GraphicObjects/ProgressBar.cs [deleted file]
Crow/src/GraphicObjects/RadioButton.cs [deleted file]
Crow/src/GraphicObjects/SaturationValueSelector.cs [deleted file]
Crow/src/GraphicObjects/ScrollBar.cs [deleted file]
Crow/src/GraphicObjects/Scroller.cs [deleted file]
Crow/src/GraphicObjects/ScrollingObject.cs [deleted file]
Crow/src/GraphicObjects/Shape.cs [deleted file]
Crow/src/GraphicObjects/Slider.cs [deleted file]
Crow/src/GraphicObjects/Spinner.cs [deleted file]
Crow/src/GraphicObjects/Splitter.cs [deleted file]
Crow/src/GraphicObjects/TabItem.cs [deleted file]
Crow/src/GraphicObjects/TabView.cs [deleted file]
Crow/src/GraphicObjects/TemplatedContainer.cs [deleted file]
Crow/src/GraphicObjects/TemplatedControl.cs [deleted file]
Crow/src/GraphicObjects/TemplatedGroup.cs [deleted file]
Crow/src/GraphicObjects/TestCairoPatch.cs [deleted file]
Crow/src/GraphicObjects/TextBox.cs [deleted file]
Crow/src/GraphicObjects/TextRun.cs [deleted file]
Crow/src/GraphicObjects/TreeView.cs [deleted file]
Crow/src/GraphicObjects/Trend.cs [deleted file]
Crow/src/GraphicObjects/VerticalStack.cs [deleted file]
Crow/src/GraphicObjects/Widget.cs [deleted file]
Crow/src/GraphicObjects/Window.cs [deleted file]
Crow/src/GraphicObjects/Wrapper.cs [deleted file]
Crow/src/GraphicObjects/XmlIgnoreAttribute.cs [deleted file]
Crow/src/Widgets/Border.cs [new file with mode: 0644]
Crow/src/Widgets/Button.cs [new file with mode: 0644]
Crow/src/Widgets/CheckBox.cs [new file with mode: 0644]
Crow/src/Widgets/ColorPicker.cs [new file with mode: 0644]
Crow/src/Widgets/ColorSelector.cs [new file with mode: 0644]
Crow/src/Widgets/ColorSlider.cs [new file with mode: 0644]
Crow/src/Widgets/ComboBox.cs [new file with mode: 0644]
Crow/src/Widgets/Container.cs [new file with mode: 0644]
Crow/src/Widgets/DataSourceChangeEventArgs.cs [new file with mode: 0644]
Crow/src/Widgets/DirectoryView.cs [new file with mode: 0644]
Crow/src/Widgets/DockStack.cs [new file with mode: 0644]
Crow/src/Widgets/DockWindow.cs [new file with mode: 0644]
Crow/src/Widgets/EnumSelector.cs [new file with mode: 0644]
Crow/src/Widgets/Expandable.cs [new file with mode: 0644]
Crow/src/Widgets/FileDialog.cs [new file with mode: 0644]
Crow/src/Widgets/GenericStack.cs [new file with mode: 0644]
Crow/src/Widgets/GraduatedSlider.cs [new file with mode: 0644]
Crow/src/Widgets/Grid.cs [new file with mode: 0644]
Crow/src/Widgets/Group.cs [new file with mode: 0644]
Crow/src/Widgets/GroupBox.cs [new file with mode: 0644]
Crow/src/Widgets/HorizontalStack.cs [new file with mode: 0644]
Crow/src/Widgets/HueSelector.cs [new file with mode: 0644]
Crow/src/Widgets/ILayoutable.cs [new file with mode: 0644]
Crow/src/Widgets/IMLContainer.cs [new file with mode: 0644]
Crow/src/Widgets/IValueChange.cs [new file with mode: 0644]
Crow/src/Widgets/Image.cs [new file with mode: 0644]
Crow/src/Widgets/Label.cs [new file with mode: 0644]
Crow/src/Widgets/ListBox.cs [new file with mode: 0644]
Crow/src/Widgets/Menu.cs [new file with mode: 0644]
Crow/src/Widgets/MenuItem.cs [new file with mode: 0644]
Crow/src/Widgets/MessageBox.cs [new file with mode: 0644]
Crow/src/Widgets/NumericControl.cs [new file with mode: 0644]
Crow/src/Widgets/Popper.cs [new file with mode: 0644]
Crow/src/Widgets/PrivateContainer.cs [new file with mode: 0644]
Crow/src/Widgets/ProgressBar.cs [new file with mode: 0644]
Crow/src/Widgets/RadioButton.cs [new file with mode: 0644]
Crow/src/Widgets/SaturationValueSelector.cs [new file with mode: 0644]
Crow/src/Widgets/ScrollBar.cs [new file with mode: 0644]
Crow/src/Widgets/Scroller.cs [new file with mode: 0644]
Crow/src/Widgets/ScrollingObject.cs [new file with mode: 0644]
Crow/src/Widgets/Shape.cs [new file with mode: 0644]
Crow/src/Widgets/Slider.cs [new file with mode: 0644]
Crow/src/Widgets/Spinner.cs [new file with mode: 0644]
Crow/src/Widgets/Splitter.cs [new file with mode: 0644]
Crow/src/Widgets/TabItem.cs [new file with mode: 0644]
Crow/src/Widgets/TabView.cs [new file with mode: 0644]
Crow/src/Widgets/TemplatedContainer.cs [new file with mode: 0644]
Crow/src/Widgets/TemplatedControl.cs [new file with mode: 0644]
Crow/src/Widgets/TemplatedGroup.cs [new file with mode: 0644]
Crow/src/Widgets/TestCairoPatch.cs [new file with mode: 0644]
Crow/src/Widgets/TextBox.cs [new file with mode: 0644]
Crow/src/Widgets/TextRun.cs [new file with mode: 0644]
Crow/src/Widgets/TreeView.cs [new file with mode: 0644]
Crow/src/Widgets/Trend.cs [new file with mode: 0644]
Crow/src/Widgets/VerticalStack.cs [new file with mode: 0644]
Crow/src/Widgets/Widget.cs [new file with mode: 0644]
Crow/src/Widgets/Window.cs [new file with mode: 0644]
Crow/src/Widgets/Wrapper.cs [new file with mode: 0644]
Crow/src/Widgets/XmlIgnoreAttribute.cs [new file with mode: 0644]

diff --git a/Crow/src/GraphicObjects/Border.cs b/Crow/src/GraphicObjects/Border.cs
deleted file mode 100644 (file)
index e5a16ec..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-//
-// Border.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.Xml.Serialization;
-using System.ComponentModel;
-using System.Diagnostics;
-using Crow.Cairo;
-
-namespace Crow
-{
-       /// <summary>
-       /// provide an easy way to get 3d border for buttons
-       /// </summary>
-       public enum BorderStyle {
-               Normal,
-               Raised,
-               Sunken
-       };
-
-       /// <summary>
-       /// simple container with border
-       /// </summary>
-       public class Border : Container
-       {
-               #region CTOR
-               protected Border () : base(){}
-               public Border (Interface iface) : base(iface){}
-               #endregion
-
-               #region private fields
-               int _borderWidth;
-               BorderStyle _borderStyle;
-               Fill raisedColor = Color.Grey;
-               Fill sunkenColor = Color.DimGrey;
-               #endregion
-
-               #region public properties
-               /// <summary>
-               /// use to define the colors of the 3d border
-               /// </summary>
-               
-               public virtual Fill RaisedColor {
-                       get { return raisedColor; }
-                       set {
-                               if (raisedColor == value)
-                                       return;
-                               raisedColor = value;
-                               NotifyValueChanged ("RaisedColor", raisedColor);
-                               RegisterForRedraw ();
-                       }
-               }
-               /// <summary>
-               /// use to define the colors of the 3d border
-               /// </summary>
-               
-               public virtual Fill SunkenColor {
-                       get { return sunkenColor; }
-                       set {
-                               if (sunkenColor == value)
-                                       return;
-                               sunkenColor = value;
-                               NotifyValueChanged ("SunkenColor", sunkenColor);
-                               RegisterForRedraw ();
-                       }
-               }
-               /// <summary>
-               /// border width in pixels
-               /// </summary>
-               [DefaultValue(1)]
-               public virtual int BorderWidth {
-                       get { return _borderWidth; }
-                       set {
-                               _borderWidth = value;
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary>
-               /// allow 3d border effects
-               /// </summary>
-               [DefaultValue(BorderStyle.Normal)]
-               public virtual BorderStyle BorderStyle {
-                       get { return _borderStyle; }
-                       set {
-                               if (_borderStyle == value)
-                                       return;
-                               _borderStyle = value;
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               #endregion
-
-               #region GraphicObject override
-               [XmlIgnore]public override Rectangle ClientRectangle {
-                       get {
-                               Rectangle cb = base.ClientRectangle;
-                               cb.Inflate (- BorderWidth);
-                               return cb;
-                       }
-               }
-
-               protected override int measureRawSize (LayoutingType lt)
-               {
-                       int tmp = base.measureRawSize (lt);
-                       return tmp < 0 ? tmp : tmp + 2 * BorderWidth;
-               }
-               protected override void onDraw (Context gr)
-               {
-                       drawborder2 (gr);
-
-                       gr.Save ();
-                       if (ClipToClientRect) {
-                               //clip to client zone
-                               CairoHelpers.CairoRectangle (gr, ClientRectangle,Math.Max(0.0, CornerRadius-Margin));
-                               gr.Clip ();
-                       }
-
-                       if (child != null)
-                               child.Paint (ref gr);
-                       gr.Restore ();
-               }
-               void drawborder2(Context gr){
-                       Rectangle rBack = new Rectangle (Slot.Size);
-
-                       //rBack.Inflate (-Margin);
-                       //                      if (BorderWidth > 0)
-                       //                              rBack.Inflate (-BorderWidth / 2);
-
-                       Background.SetAsSource (gr, rBack);
-                       CairoHelpers.CairoRectangle(gr, rBack, CornerRadius);
-                       gr.Fill ();
-
-
-                       if (BorderStyle == BorderStyle.Normal) {
-                               if (BorderWidth > 0) {
-                                       Foreground.SetAsSource (gr, rBack);
-                                       CairoHelpers.CairoRectangle (gr, rBack, CornerRadius, BorderWidth);
-                               }
-                       } else {
-                               gr.LineWidth = 1.0;
-                               if (CornerRadius > 0.0) {
-                                       double radius = CornerRadius;
-                                       if ((radius > rBack.Height / 2.0) || (radius > rBack.Width / 2.0))
-                                               radius = Math.Min (rBack.Height / 2.0, rBack.Width / 2.0);
-                                       gr.SetSourceColor (sunkenColor);
-                                       gr.MoveTo (0.5 + rBack.Left, -0.5 + rBack.Bottom - radius);
-                                       gr.ArcNegative (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom - radius, radius, Math.PI, Math.PI * 0.75);
-                                       gr.MoveTo (0.5 + rBack.Left, -0.5 + rBack.Bottom - radius);
-                                       gr.LineTo (0.5 + rBack.Left, 0.5 + rBack.Top + radius);
-                                       gr.Arc (0.5 + rBack.Left + radius, 0.5 + rBack.Top + radius, radius, Math.PI, Math.PI * 1.5);
-                                       gr.LineTo (-0.5 + rBack.Right - radius, 0.5 + rBack.Top);
-                                       gr.Arc (-0.5 + rBack.Right - radius, 0.5 + rBack.Top + radius, radius, Math.PI * 1.5, Math.PI * 1.75);
-                                       gr.Stroke ();
-                                       if (BorderStyle == BorderStyle.Raised) {
-                                               gr.MoveTo (-1.5 + rBack.Right, 1.5 + rBack.Top + radius);
-                                               gr.ArcNegative (-0.5 + rBack.Right - radius, 0.5 + rBack.Top + radius, radius - 1.0, 0, -Math.PI * 0.25);
-                                               gr.MoveTo (-1.5 + rBack.Right, 1.5 + rBack.Top + radius);
-                                               gr.LineTo (-1.5 + rBack.Right, -1.5 + rBack.Bottom - radius);
-                                               gr.Arc (-0.5 + rBack.Right - radius, -0.5 + rBack.Bottom - radius, radius - 1.0, 0, Math.PI / 2.0);
-                                               gr.LineTo (1.5 + rBack.Left + radius, -1.5 + rBack.Bottom);
-                                               gr.Arc (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom - radius, radius - 1.0, Math.PI / 2.0, Math.PI * 0.75);
-                                               gr.Stroke ();
-
-                                               gr.SetSourceColor (raisedColor);
-                                               gr.MoveTo (1.5 + rBack.Left, -1.5 + rBack.Bottom - radius);
-                                               gr.ArcNegative (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom - radius, radius - 1.0, Math.PI, Math.PI * 0.75);
-                                               gr.MoveTo (1.5 + rBack.Left, -1.5 + rBack.Bottom - radius);
-                                               gr.LineTo (1.5 + rBack.Left, 1.5 + rBack.Top + radius);
-                                               gr.Arc (0.5 + rBack.Left + radius, 0.5 + rBack.Top + radius, radius - 1.0, Math.PI, Math.PI * 1.5);
-                                               gr.LineTo (-1.5 + rBack.Right - radius, 1.5 + rBack.Top);
-                                               gr.Arc (-0.5 + rBack.Right - radius, 0.5 + rBack.Top + radius, radius - 1.0, Math.PI * 1.5, Math.PI * 1.75);
-                                       } else {
-                                               gr.Stroke ();
-                                               gr.SetSourceColor (raisedColor);
-                                       }
-                                       gr.MoveTo (-0.5 + rBack.Right, 0.5 + rBack.Top + radius);
-                                       gr.ArcNegative (-0.5 + rBack.Right - radius, 0.5 + rBack.Top + radius, radius, 0, -Math.PI * 0.25);
-                                       gr.MoveTo (-0.5 + rBack.Right, 0.5 + rBack.Top + radius);
-                                       gr.LineTo (-0.5 + rBack.Right, -0.5 + rBack.Bottom - radius);
-                                       gr.Arc (-0.5 + rBack.Right - radius, -0.5 + rBack.Bottom - radius, radius, 0, Math.PI / 2.0);
-                                       gr.LineTo (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom);
-                                       gr.Arc (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom - radius, radius, Math.PI / 2.0, Math.PI * 0.75);
-                                       gr.Stroke ();
-                               } else {
-                                       gr.SetSourceColor (sunkenColor);
-                                       gr.MoveTo (0.5 + rBack.Left, rBack.Bottom);
-                                       gr.LineTo (0.5 + rBack.Left, 0.5 + rBack.Y);
-                                       gr.LineTo (rBack.Right, 0.5 + rBack.Y);
-                                       if (BorderStyle == BorderStyle.Raised) {
-                                               gr.MoveTo (-1.5 + rBack.Right, 2.0 + rBack.Y);
-                                               gr.LineTo (-1.5 + rBack.Right, -1.5 + rBack.Bottom);
-                                               gr.LineTo (2.0 + rBack.Left, -1.5 + rBack.Bottom);
-                                               gr.Stroke ();
-                                               gr.SetSourceColor (raisedColor);
-                                               gr.MoveTo (1.5 + rBack.Left, -1.0 + rBack.Bottom);
-                                               gr.LineTo (1.5 + rBack.Left, 1.5 + rBack.Y);
-                                               gr.LineTo (rBack.Right, 1.5 + rBack.Y);
-                                       } else {
-                                               gr.Stroke ();
-                                               gr.SetSourceColor (raisedColor);
-                                       }
-                                       gr.MoveTo (-0.5 + rBack.Right, 1.5 + rBack.Y);
-                                       gr.LineTo (-0.5 + rBack.Right, -0.5 + rBack.Bottom);
-                                       gr.LineTo (1.0 + rBack.Left, -0.5 + rBack.Bottom);
-                                       gr.Stroke ();
-                               }
-                       }
-               }
-               void drawborder1(Context gr){
-                       Rectangle rBack = new Rectangle (Slot.Size);
-
-                       //rBack.Inflate (-Margin);
-                       //                      if (BorderWidth > 0)
-                       //                              rBack.Inflate (-BorderWidth / 2);
-
-                       Background.SetAsSource (gr, rBack);
-                       CairoHelpers.CairoRectangle(gr, rBack, CornerRadius);
-                       gr.Fill ();
-
-                       double bw = _borderWidth;
-                       double crad = CornerRadius;
-
-                       if (bw > 0) {
-                               if (BorderStyle == BorderStyle.Normal)
-                                       Foreground.SetAsSource (gr, rBack);
-                               else {
-                                       if (BorderStyle == BorderStyle.Sunken)
-                                               gr.SetSourceColor (raisedColor);
-                                       else
-                                               gr.SetSourceColor (sunkenColor);
-
-                                       CairoHelpers.CairoRectangle (gr, rBack, crad, bw);
-
-                                       if (BorderStyle == BorderStyle.Sunken)
-                                               gr.SetSourceColor (sunkenColor);
-                                       else
-                                               gr.SetSourceColor (raisedColor);
-
-                                       bw /= 2.0;
-                                       rBack.Width -= (int)Math.Round(bw);
-                                       rBack.Height -= (int)Math.Round(bw);
-                               }
-
-                               CairoHelpers.CairoRectangle (gr, rBack, crad, bw);
-                       }
-               }
-               #endregion
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Button.cs b/Crow/src/GraphicObjects/Button.cs
deleted file mode 100644 (file)
index 8b15c2e..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-// Button.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.Collections.Generic;
-using System.Linq;
-using System.Text;
-//using OpenTK.Graphics.OpenGL;
-
-using System.Diagnostics;
-
-using System.Xml.Serialization;
-using Crow.Cairo;
-using System.ComponentModel;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated button control
-       /// </summary>
-    public class Button : TemplatedContainer
-    {
-               #region CTOR
-               protected Button() : base() {}
-               public Button (Interface iface) : base(iface){}
-               #endregion
-
-               string image;
-               bool isPressed;
-
-               public event EventHandler Pressed;
-               public event EventHandler Released;
-
-               #region GraphicObject Overrides
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       IsPressed = true;
-
-                       base.onMouseDown (sender, e);
-
-                       //TODO:remove
-                       NotifyValueChanged ("State", "pressed");
-               }
-               public override void onMouseUp (object sender, MouseButtonEventArgs e)
-               {
-                       IsPressed = false;
-
-                       base.onMouseUp (sender, e);
-
-                       //TODO:remove
-                       NotifyValueChanged ("State", "normal");
-               }
-               #endregion
-
-               [DefaultValue("#Crow.Images.button.svg")]
-               public string Image {
-                       get { return image; }
-                       set {
-                               if (image == value)
-                                       return;
-                               image = value;
-                               NotifyValueChanged ("Image", image);
-                       }
-               }
-               [DefaultValue(false)]
-               public bool IsPressed
-               {
-                       get { return isPressed; }
-                       set
-                       {
-                               if (isPressed == value)
-                                       return;
-
-                               isPressed = value;
-
-                               NotifyValueChanged ("IsPressed", isPressed);
-
-                               if (isPressed)
-                                       Pressed.Raise (this, null);
-                               else
-                                       Released.Raise (this, null);
-                       }
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/CheckBox.cs b/Crow/src/GraphicObjects/CheckBox.cs
deleted file mode 100644 (file)
index 7dc2b07..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// CheckBox.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.ComponentModel;
-using System.Xml.Serialization;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated checkbox control
-       /// </summary>
-       public class CheckBox : TemplatedControl
-       {
-               #region CTOR
-               protected CheckBox() : base(){}
-               public CheckBox (Interface iface) : base(iface){}
-               #endregion
-
-               bool isChecked;
-
-               public event EventHandler Checked;
-               public event EventHandler Unchecked;
-
-               [DefaultValue(false)]
-               public bool IsChecked
-               {
-                       get { return isChecked; }
-                       set
-                       {
-                               if (isChecked == value)
-                                       return;
-
-                               isChecked = value;
-
-                               NotifyValueChanged ("IsChecked", value);
-
-                               if (isChecked)
-                                       Checked.Raise (this, null);
-                               else
-                                       Unchecked.Raise (this, null);
-                       }
-               }
-
-               public override void onMouseClick (object sender, MouseButtonEventArgs e)
-               {
-                       IsChecked = !IsChecked;
-                       base.onMouseClick (sender, e);
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/ColorPicker.cs b/Crow/src/GraphicObjects/ColorPicker.cs
deleted file mode 100644 (file)
index 9283771..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-//
-// ColorPicker.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated color selector control
-       /// </summary>
-       public class ColorPicker : TemplatedControl
-       {
-               #region CTOR
-               protected ColorPicker() : base(){}
-               public ColorPicker (Interface iface) : base(iface){}
-               #endregion
-
-               const double div = 255.0;
-               const double colDiv = 1.0 / div;
-
-               Color curColor;
-               double h,s,v;
-
-               
-               public virtual double R {
-                       get { return Math.Round(curColor.R * div); }
-                       set {
-                               if (R == value)
-                                       return;
-                               curColor.R = value * colDiv;
-                               NotifyValueChanged ("R", R);
-                               hsvFromRGB ();
-                               notifyCurColorHasChanged ();
-                       }
-               }
-               
-               public virtual double G {
-                       get { return Math.Round(curColor.G * div); }
-                       set {
-                               if (G == value)
-                                       return;
-                               curColor.G = value * colDiv;
-                               NotifyValueChanged ("G", G);
-                               notifyCurColorHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               
-               public virtual double B {
-                       get { return Math.Round(curColor.B * div); }
-                       set {
-                               if (B == value)
-                                       return;
-                               curColor.B = value * colDiv;
-                               NotifyValueChanged ("B", B);
-                               notifyCurColorHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               
-               public virtual double A {
-                       get { return Math.Round(curColor.A * div); }
-                       set {
-                               if (A == value)
-                                       return;
-                               curColor.A = value * colDiv;
-                               NotifyValueChanged ("A", A);
-                               notifyCurColorHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               
-               public virtual double H {
-                       get { return Math.Round (h, 3); }
-                       set {
-                               if (H == value)
-                                       return;
-                               h = value;
-                               NotifyValueChanged ("H", H);
-                               rgbFromHSV ();
-                       }
-               }
-               
-               public virtual double S {
-                       get { return Math.Round (s, 2); }
-                       set {
-                               if (s == value)
-                                       return;
-                               s = value;
-                               NotifyValueChanged ("S", S);
-                               rgbFromHSV ();
-                       }
-               }
-               
-               public virtual double V {
-                       get { return Math.Round (v, 2); }
-                       set {
-                               if (v == value)
-                                       return;
-                               v = value;
-                               NotifyValueChanged ("V", V);
-                               rgbFromHSV ();
-                       }
-               }
-
-               
-               public virtual Fill SelectedColor {
-                       get { return new SolidColor(curColor); }
-                       set {
-                               if (value == null)
-                                       curColor = Color.White;
-                               else if (value is SolidColor) {
-                                       Color c = (value as SolidColor).color;
-                                       if (curColor == c)
-                                               return;
-                                       curColor = c;
-                               }
-                               notifyCurColorHasChanged ();
-                               notifyRGBAHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               
-               public virtual Color SelectedRawColor {
-                       get { return curColor; }
-                       set {
-                               if (curColor == value)
-                                       return;
-                               curColor = value;
-                               notifyCurColorHasChanged ();
-                               notifyRGBAHasChanged ();
-                               hsvFromRGB ();
-                       }
-               }
-               void notifyCurColorHasChanged(){
-                       NotifyValueChanged ("SelectedColor", SelectedColor);
-                       NotifyValueChanged ("SelectedRawColor", curColor);
-                       string n = curColor.ToString ();
-                       if (char.IsLetter(n[0]))
-                               NotifyValueChanged ("SelectedColorName", n);
-                       else
-                               NotifyValueChanged ("SelectedColorName", "-");
-                       string tmp = ((int)Math.Round (R)).ToString ("X2") +
-                                    ((int)Math.Round (G)).ToString ("X2") +
-                                    ((int)Math.Round (B)).ToString ("X2");
-                       if (curColor.A < 1.0)
-                               tmp += ((int)Math.Round (A)).ToString ("X2");
-                       NotifyValueChanged ("HexColor", tmp);
-               }
-               void notifyRGBAHasChanged(){
-                       NotifyValueChanged ("R", R);
-                       NotifyValueChanged ("G", G);
-                       NotifyValueChanged ("B", B);
-                       NotifyValueChanged ("A", A);
-               }
-               void notifyHSVHasChanged(){
-                       NotifyValueChanged ("H", H);
-                       NotifyValueChanged ("S", S);
-                       NotifyValueChanged ("V", V);
-               }
-               void hsvFromRGB(){
-                       Color c = curColor;
-                       c.ResetName ();
-                       double min = Math.Min (c.R, Math.Min (c.G, c.B));       //Min. value of RGB
-                       double max = Math.Max (c.R, Math.Max (c.G, c.B));       //Max. value of RGB
-                       double diff = max - min;                                                        //Delta RGB value
-
-                       v = max;
-
-                       if ( diff == 0 )//This is a gray, no chroma...
-                       {
-                               h = 0;
-                               s = 0;
-                       }else{//Chromatic data...
-                               s = diff / max;
-
-                               double diffR = (((max - c.R) / 6.0) + (diff / 2.0)) / diff;
-                               double diffG = (((max - c.G) / 6.0) + (diff / 2.0)) / diff;
-                               double diffB = (((max - c.B) / 6.0) + (diff / 2.0)) / diff;
-
-                               if (c.R == max)
-                                       h = diffB - diffG;
-                               else if (c.G == max)
-                                       h = (1.0 / 3.0) + diffR - diffB;
-                               else if (c.B == max)
-                                       h = (2.0 / 3.0) + diffG - diffR;
-
-                               if (h < 0)
-                                       h += 1;
-                               if (h > 1)
-                                       h -= 1;
-
-                       }
-                       notifyHSVHasChanged ();
-               }
-               void rgbFromHSV(){
-                       curColor = Color.FromHSV (h, v, s, curColor.A);
-                       notifyCurColorHasChanged ();
-                       notifyRGBAHasChanged ();
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/ColorSelector.cs b/Crow/src/GraphicObjects/ColorSelector.cs
deleted file mode 100644 (file)
index 83e6962..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// ColorSelector.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       /// <summary>
-       /// simple squarred rgb color selector
-       /// </summary>
-       [DesignIgnore]
-       public class ColorSelector : Widget
-       {
-               #region CTOR
-               protected ColorSelector() : base(){}
-               public ColorSelector (Interface iface) : base(iface){}
-               #endregion
-
-               protected Point mousePos;
-
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseMove (sender, e);
-                       if (IFace.Mouse.LeftButton == ButtonState.Released)
-                               return;
-                       updateMouseLocalPos (e.Position);
-               }
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseDown (sender, e);
-                       if (e.Button == MouseButton.Left)
-                               updateMouseLocalPos (e.Position);
-               }
-
-               protected virtual void updateMouseLocalPos(Point mPos){
-                       Rectangle r = ScreenCoordinates (Slot);
-                       Rectangle cb = ClientRectangle;
-                       mousePos = mPos - r.Position;
-
-                       mousePos.X = Math.Max(cb.X, mousePos.X);
-                       mousePos.X = Math.Min(cb.Right, mousePos.X);
-                       mousePos.Y = Math.Max(cb.Y, mousePos.Y);
-                       mousePos.Y = Math.Min(cb.Bottom, mousePos.Y);
-
-                       RegisterForRedraw ();
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/ColorSlider.cs b/Crow/src/GraphicObjects/ColorSlider.cs
deleted file mode 100644 (file)
index 9a7e470..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.ComponentModel;
-using Crow.Cairo;
-
-namespace Crow
-{
-       /// <summary>
-       /// simple squarred rgb color selector
-       /// </summary>
-       [DesignIgnore]
-       public class ColorSlider : Widget
-       {
-               #region CTOR
-               protected ColorSlider() : base(){}
-               public ColorSlider (Interface iface) : base(iface){}
-               #endregion
-
-               protected Point mousePos;
-               Orientation orientation;
-               CursorType cursorType = CursorType.Pentagone;
-               ColorComponent component;
-               Color currentColor = Color.Black;
-               double currentValue;
-
-               [DefaultValue (Orientation.Horizontal)]
-               public Orientation Orientation {
-                       get => orientation;
-                       set {
-                               if (orientation == value)
-                                       return;
-                               orientation = value;
-                               NotifyValueChanged ("Orientation", orientation);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               [DefaultValue (CursorType.Pentagone)]
-               public CursorType CursorType {
-                       get => cursorType;
-                       set {
-                               if (cursorType == value)
-                                       return;
-                               cursorType = value;
-                               NotifyValueChanged ("CursorType", cursorType);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue (ColorComponent.Value)]
-               public ColorComponent Component {
-                       get => component;
-                       set {
-                               if (component == value)
-                                       return;
-                               component = value;
-                               NotifyValueChanged ("Component", component);
-                               RegisterForRedraw ();
-                       }
-               }
-               public Color CurrentColor {
-                       get => currentColor;
-                       set {
-                               if (currentColor == value)
-                                       return;
-                               currentColor = value;
-                               switch (component) {
-                               case ColorComponent.Red:
-                                       if (currentValue != currentColor.R) {
-                                               currentValue = currentColor.R;
-                                               updateMousePosFromComponentValue ();
-                                       }
-                                       break;
-                               case ColorComponent.Green:
-                                       if (currentValue != currentColor.G) {
-                                               currentValue = currentColor.G;
-                                               updateMousePosFromComponentValue ();
-                                       }
-                                       break;
-                               case ColorComponent.Blue:
-                                       if (currentValue != currentColor.B) {
-                                               currentValue = currentColor.B;
-                                               updateMousePosFromComponentValue ();
-                                       }
-                                       break;
-                               case ColorComponent.Alpha:
-                                       if (currentValue != currentColor.A) {
-                                               currentValue = currentColor.A;
-                                               updateMousePosFromComponentValue ();
-                                       }
-                                       break;
-                               case ColorComponent.Hue:
-                                       if (currentValue != currentColor.Hue) {
-                                               currentValue = currentColor.Hue;
-                                               updateMousePosFromComponentValue ();
-                                       }
-                                       break;
-                               case ColorComponent.Saturation:
-                                       if (currentValue != currentColor.Saturation) {
-                                               currentValue = currentColor.Saturation;
-                                               updateMousePosFromComponentValue ();
-                                       }
-                                       break;
-                               case ColorComponent.Value:
-                                       if (currentValue != currentColor.Value) {
-                                               currentValue = currentColor.Value;
-                                               updateMousePosFromComponentValue ();
-                                       }
-                                       break;
-                               }
-                               NotifyValueChanged ("CurrentColor", currentColor);
-                               RegisterForRedraw ();
-                       }
-               }
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseMove (sender, e);
-                       if (IFace.Mouse.LeftButton == ButtonState.Released)
-                               return;
-                       updateMouseLocalPos (e.Position);
-               }
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseDown (sender, e);
-                       if (e.Button == MouseButton.Left)
-                               updateMouseLocalPos (e.Position);
-               }
-
-               protected override void onDraw (Context gr) {
-                       base.onDraw (gr);
-
-                       RectangleD r = ClientRectangle;
-                       r.Height -= 4;
-                       r.Y += 2;
-
-                       Gradient.Type gt = Gradient.Type.Horizontal;
-                       if (Orientation == Orientation.Vertical)
-                               gt = Gradient.Type.Vertical;
-
-                       Gradient grad = new Gradient (gt);
-                       Color c = currentColor;
-
-                       switch (component) {
-                       case ColorComponent.Red:
-                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (0, c.G, c.B, c.A)));
-                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, c.G, c.B, c.A)));
-                               break;
-                       case ColorComponent.Green:
-                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (c.R, 0, c.B, c.A)));
-                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (c.R, 1, c.B, c.A)));
-                               break;
-                       case ColorComponent.Blue:
-                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (c.R, c.G, 0, c.A)));
-                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (c.R, c.G, 1, c.A)));
-                               break;
-                       case ColorComponent.Alpha:
-                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (c.R, c.G, c.B, 0)));
-                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (c.R, c.G, c.B, 1)));
-                               break;
-                       case ColorComponent.Hue:
-                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 0, 0, 1)));
-                               grad.Stops.Add (new Gradient.ColorStop (0.167, new Color (1, 1, 0, 1)));
-                               grad.Stops.Add (new Gradient.ColorStop (0.333, new Color (0, 1, 0, 1)));
-                               grad.Stops.Add (new Gradient.ColorStop (0.5, new Color (0, 1, 1, 1)));
-                               grad.Stops.Add (new Gradient.ColorStop (0.667, new Color (0, 0, 1, 1)));
-                               grad.Stops.Add (new Gradient.ColorStop (0.833, new Color (1, 0, 1, 1)));
-                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, 0, 0, 1)));
-                               break;
-                       case ColorComponent.Saturation:
-                               grad.Stops.Add (new Gradient.ColorStop (0, Color.FromHSV (c.Hue, c.Value, 0.0, c.A)));
-                               grad.Stops.Add (new Gradient.ColorStop (1, Color.FromHSV (c.Hue, c.Value, 1.0, c.A)));
-                               break;
-                       case ColorComponent.Value:
-                               grad.Stops.Add (new Gradient.ColorStop (0, Color.FromHSV (c.Hue, 0.0, c.Saturation, c.A)));
-                               grad.Stops.Add (new Gradient.ColorStop (1, Color.FromHSV (c.Hue, 1.0, c.Saturation, c.A)));
-                               break;
-                       }
-
-                       grad.SetAsSource (gr, r);
-                       CairoHelpers.CairoRectangle (gr, r, CornerRadius);
-                       gr.Fill ();
-
-                       r = ClientRectangle;
-
-                       switch (cursorType) {
-                       case CursorType.Rectangle:
-                               if (Orientation == Orientation.Horizontal) {
-                                       r.Width = 5;
-                                       r.X = mousePos.X - 2.5;
-                               } else {
-                                       r.Height = 5;
-                                       r.Y = mousePos.Y - 2.5;
-                               }
-                               CairoHelpers.CairoRectangle (gr, r, 1);
-                               break;
-                       case CursorType.Circle:
-                               if (Orientation == Orientation.Horizontal)
-                                       gr.Arc (mousePos.X, r.Center.Y, 3.5, 0, Math.PI * 2.0);
-                               else
-                                       gr.Arc (r.Center.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
-                               break;
-                       case CursorType.Pentagone:
-                               if (Orientation == Orientation.Horizontal) {
-                                       r.Width = 5;
-                                       r.X = mousePos.X - 2.5;
-                                       double y = r.CenterD.Y - r.Height * 0.2;
-                                       gr.MoveTo (mousePos.X, y);
-                                       y += r.Height * 0.15;
-                                       gr.LineTo (r.Right, y);
-                                       gr.LineTo (r.Right, r.Bottom - 0.5);
-                                       gr.LineTo (r.Left, r.Bottom - 0.5);
-                                       gr.LineTo (r.Left, y);
-                                       gr.ClosePath ();
-                               } else {
-                               }
-                               break;
-                       }
-
-                       gr.SetSourceColor (Color.Black);
-                       gr.LineWidth = 2.0;
-                       gr.StrokePreserve ();
-                       gr.SetSourceColor (Color.White);
-                       gr.LineWidth = 1.0;
-                       gr.Stroke ();
-               }
-               public override void OnLayoutChanges (LayoutingType layoutType) {
-                       base.OnLayoutChanges (layoutType);
-
-                       if (Orientation == Orientation.Horizontal) {
-                               if (layoutType == LayoutingType.Width)
-                                       updateMousePosFromComponentValue ();
-                       } else if (layoutType == LayoutingType.Height)
-                               updateMousePosFromComponentValue ();
-               }
-               void updateMousePosFromComponentValue () {
-                       if (Orientation == Orientation.Horizontal)
-                               mousePos.X = (int)Math.Floor (currentValue * ClientRectangle.Width);
-                       else
-                               mousePos.Y = (int)Math.Floor (currentValue * ClientRectangle.Height);
-                       RegisterForRedraw ();
-               }
-
-               protected virtual void updateMouseLocalPos(Point mPos){
-                       Rectangle r = ScreenCoordinates (Slot);
-                       Rectangle cb = ClientRectangle;
-                       mousePos = mPos - r.Position;
-
-                       mousePos.X = Math.Max(cb.X, mousePos.X);
-                       mousePos.X = Math.Min(cb.Right, mousePos.X);
-                       mousePos.Y = Math.Max(cb.Y, mousePos.Y);
-                       mousePos.Y = Math.Min(cb.Bottom, mousePos.Y);
-
-                       if (Orientation == Orientation.Horizontal)
-                               currentValue = (double)mousePos.X / ClientRectangle.Width;
-                       else
-                               currentValue = (double)mousePos.Y / ClientRectangle.Height;
-                       Color c = currentColor;
-                       switch (component) {
-                       case ColorComponent.Red:
-                               CurrentColor = new Color(currentValue, c.G, c.B, c.A);
-                               break;
-                       case ColorComponent.Green:
-                               CurrentColor = new Color (c.R, currentValue, c.B, c.A);
-                               break;
-                       case ColorComponent.Blue:
-                               CurrentColor = new Color (c.R, c.G, currentValue, c.A);
-                               break;
-                       case ColorComponent.Alpha:
-                               CurrentColor = new Color (c.R, c.G, c.B, currentValue);
-                               break;
-                       case ColorComponent.Hue:
-                               CurrentColor = Color.FromHSV (currentValue, c.Value, c.Saturation, c.A);
-                               break;
-                       case ColorComponent.Saturation:
-                               CurrentColor = Color.FromHSV (c.Hue, c.Value, currentValue, c.A);
-                               break;
-                       case ColorComponent.Value:
-                               CurrentColor = Color.FromHSV (c.Hue, currentValue, c.Saturation, c.A);
-                               break;
-                       }
-                       //NotifyValueChanged ("CurrentColor", currentColor);
-                       //RegisterForRedraw ();
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/ComboBox.cs b/Crow/src/GraphicObjects/ComboBox.cs
deleted file mode 100644 (file)
index 6122705..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// ComboBox.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.Xml.Serialization;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated control for selecting value in a pop up list
-       /// </summary>
-       public class ComboBox : ListBox
-    {
-               #region CTOR
-               protected ComboBox() : base(){}
-               public ComboBox (Interface iface) : base(iface){}
-               #endregion
-
-               Size minimumPopupSize = "10,10";
-               [XmlIgnore]public Size MinimumPopupSize{
-                       get { return minimumPopupSize; }
-                       set {
-                               minimumPopupSize = value;
-                               NotifyValueChanged ("MinimumPopupSize", minimumPopupSize);
-                       }
-               }
-
-               public override void OnLayoutChanges (LayoutingType layoutType)
-               {
-                       base.OnLayoutChanges (layoutType);
-
-                       if (layoutType == LayoutingType.Width)
-                               MinimumPopupSize = new Size (this.Slot.Width, minimumPopupSize.Height);                 
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/Container.cs b/Crow/src/GraphicObjects/Container.cs
deleted file mode 100644 (file)
index ce54514..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-//
-// Container.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.Xml.Serialization;
-using System.Reflection;
-using System.ComponentModel;
-using System.Linq;
-using System.Threading;
-
-namespace Crow
-{
-       /// <summary>
-       /// simple container accepting one child
-       /// </summary>
-    public class Container : PrivateContainer
-    {
-               #if DESIGN_MODE
-               public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem)
-               {
-                       if (this.design_isTGItem)
-                               return;
-                       base.getIML (doc, parentElem);
-                       if (child == null)
-                               return;
-                       child.getIML (doc, parentElem.LastChild);
-               }
-               #endif
-
-               #region CTOR
-               protected Container() : base(){}
-               public Container (Interface iface) : base(iface){}
-               #endregion
-
-               [XmlIgnore]public Widget Child {
-                       get { return child; }
-                       set { base.SetChild(value); }
-               }
-               /// <summary>
-               /// override this to handle specific steps in child addition in derived class,
-               /// and don't forget to call the base.SetChild
-               /// </summary>
-               public new virtual void SetChild(Widget _child)
-               {
-                       base.SetChild (_child);
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/DataSourceChangeEventArgs.cs b/Crow/src/GraphicObjects/DataSourceChangeEventArgs.cs
deleted file mode 100644 (file)
index a251935..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// DataSourceChangeEventArgs.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;
-
-namespace Crow
-{
-       public class DataSourceChangeEventArgs : EventArgs
-       {
-               public object OldDataSource;
-               public object NewDataSource;
-
-               public DataSourceChangeEventArgs (object oldDataSource, object newDataSource) : base()
-               {
-                       OldDataSource = oldDataSource;
-                       NewDataSource = newDataSource;
-               }
-               public override string ToString ()
-               {
-                       return string.Format ("DSChangeEA: {0} => {1}", OldDataSource, NewDataSource);
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/DirectoryView.cs b/Crow/src/GraphicObjects/DirectoryView.cs
deleted file mode 100644 (file)
index b021789..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-//
-// DirectoryView.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.Xml.Serialization;
-using System.ComponentModel;
-using System.IO;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated directory viewer
-       /// </summary>
-       public class DirectoryView : TemplatedControl
-       {
-               #region CTOR
-               protected DirectoryView() : base(){}
-               public DirectoryView (Interface iface) : base(iface){}
-               #endregion
-
-               #region events
-               public event EventHandler<SelectionChangeEventArgs> SelectedItemChanged;
-               #endregion
-
-               string currentDirectory = "/";
-               bool showFiles, showHidden;
-               string fileMask = "*.*";
-
-               object _selectedItem;
-               [XmlIgnore]public object SelectedItem {
-                       get {
-                               return _selectedItem;
-                       }
-                       set { 
-                               if (value == _selectedItem)
-                                       return;
-                               _selectedItem = value;
-                               NotifyValueChanged ("SelectedItem", _selectedItem);
-                       }
-               }
-               [DefaultValue(true)]
-               public virtual bool ShowFiles {
-                       get { return showFiles; }
-                       set {
-                               if (showFiles == value)
-                                       return;
-                               showFiles = value;
-                               NotifyValueChanged ("ShowFiles", showFiles);
-                               NotifyValueChanged ("FileSystemEntries", FileSystemEntries);
-                       }
-               }
-               [DefaultValue(false)]
-               public virtual bool ShowHidden {
-                       get { return showHidden; }
-                       set {
-                               if (showHidden == value)
-                                       return;
-                               showHidden = value;
-                               NotifyValueChanged ("ShowHidden", showHidden);
-                               NotifyValueChanged ("FileSystemEntries", FileSystemEntries);
-                       }
-               }
-               [DefaultValue("*.*")]
-               public virtual string FileMask {
-                       get { return fileMask; }
-                       set {
-                               if (fileMask == value)
-                                       return;
-                               fileMask = value;
-                               NotifyValueChanged ("FileMask", fileMask);
-                               NotifyValueChanged ("FileSystemEntries", FileSystemEntries);
-                       }
-               }
-               [DefaultValue("/")]
-               public virtual string CurrentDirectory {
-                       get { return currentDirectory; }
-                       set {
-                               if (currentDirectory == value)
-                                       return;
-                               currentDirectory = value;
-                               NotifyValueChanged ("CurrentDirectory", currentDirectory);
-                               NotifyValueChanged ("FileSystemEntries", FileSystemEntries);
-                       }
-               }
-               [XmlIgnore]public FileSystemInfo[] FileSystemEntries {
-                       get {
-                               try {
-                                       if (string.IsNullOrEmpty(CurrentDirectory))
-                                               return null;
-                                       DirectoryInfo di = new DirectoryInfo(CurrentDirectory);
-                                       List<FileSystemInfo> fi = new List<FileSystemInfo> (di.GetDirectories());
-                                       if (showFiles && !string.IsNullOrEmpty(fileMask))
-                                               fi.AddRange(di.GetFiles(fileMask));
-                                       return showHidden ?
-                                               fi.ToArray() :
-                                               fi.Where(f=>!f.Attributes.HasFlag (FileAttributes.Hidden)).ToArray();
-                               } catch (Exception ex) {
-                                       Console.WriteLine (ex.ToString ());
-                                       return null;
-                               }
-                       }
-               }
-               public void onSelectedItemChanged (object sender, SelectionChangeEventArgs e){
-                       if (e.NewValue == SelectedItem)
-                               return;
-                       SelectedItem = e.NewValue;
-                       SelectedItemChanged.Raise (this, e);
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/DockStack.cs b/Crow/src/GraphicObjects/DockStack.cs
deleted file mode 100644 (file)
index a52c7f6..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-//
-// DockStack.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 Crow.IML;
-using System.Linq;
-using System.Text;
-using System.IO;
-
-namespace Crow
-{
-       [DesignIgnore]
-       public class DockStack : GenericStack
-       {               
-               #region CTor
-               public DockStack ()     {}
-               public DockStack (Interface iface) : base (iface) {}
-               #endregion
-
-               /*static int color = 10;
-
-               protected override void onInitialized (object sender, EventArgs e)
-               {
-                       base.onInitialized (sender, e);
-                       Background = Color.ColorDic.Values.ToList()[color++];
-               }*/
-               public override void AddChild (Widget g)
-               {
-                       base.AddChild (g);
-                       if (localLogicalParentIsNull)
-                               g.LogicalParent = this;
-                       else
-                               g.LogicalParent = this.LogicalParent;
-               }
-               public override void InsertChild (int idx, Widget g)
-               {
-                       base.InsertChild (idx, g);
-                       g.LogicalParent = this.LogicalParent;
-               }
-
-               public override bool PointIsIn (ref Point m)
-               {                       
-                       if (!base.PointIsIn(ref m))
-                               return false;
-
-                       Group p = Parent as Group;
-                       if (p != null) {
-                               childrenRWLock.EnterReadLock ();
-                               for (int i = p.Children.Count - 1; i >= 0; i--) {
-                                       if (p.Children [i] == this)
-                                               break;
-                                       if (p.Children [i].IsDragged)
-                                               continue;
-                                       if (p.Children [i].Slot.ContainsOrIsEqual (m)) {
-                                               childrenRWLock.ExitReadLock ();
-                                               return false;
-                                       }
-                               }
-                               childrenRWLock.ExitReadLock ();
-                       }
-
-                       return Slot.ContainsOrIsEqual(m);
-               }
-
-//             public override void OnLayoutChanges (LayoutingType layoutType)
-//             {
-//                     base.OnLayoutChanges (layoutType);
-//
-//                     if ((layoutType & LayoutingType.Sizing) > 0)
-//                             computeRects();                 
-//             }
-
-               Rectangle rIn = default(Rectangle);
-               double dockThresh = 0.2;
-               Widget focusedChild;
-               internal Widget stretchedChild;
-
-               void getFocusedChild (Point lm) {
-                       Rectangle cb = ClientRectangle;
-
-                       childrenRWLock.EnterReadLock ();
-                       foreach (Widget c in Children) {
-                               Rectangle bounds = c.Slot + cb.Position;
-                               if (!bounds.ContainsOrIsEqual (lm))
-                                       continue;
-                               rIn = bounds;
-                               focusedChild = c;
-                               break;
-                       }
-                       childrenRWLock.ExitReadLock ();                 
-               }
-
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       if (IsDropTarget) {                             
-                               DockWindow dw = IFace.DragAndDropOperation.DragSource as DockWindow;
-                               if (dw == null || dw.IsDocked) {
-                                       base.onMouseMove (sender, e);
-                                       return;
-                               }
-
-                               Alignment curDockPos = dw.DockingPosition;
-                               dw.DockingPosition = Alignment.Undefined;
-
-                               Rectangle cb = ClientRectangle;
-                               Point lm = ScreenPointToLocal (e.Position);
-
-                               if (Children.Count == 0) {
-                                       Rectangle r = cb;
-                                       r.Inflate (r.Width / -5, r.Height / -5);
-                                       if (r.ContainsOrIsEqual(lm))
-                                               dw.DockingPosition = Alignment.Center;
-                               } else {
-                                       rIn = cb;
-
-                                       if (Orientation == Orientation.Horizontal || Children.Count == 1) {
-                                               if (lm.Y > cb.Top + cb.Height / 3 && lm.Y < cb.Bottom - cb.Height / 3) {
-                                                       if (lm.X < cb.Left + cb.Width / 3)
-                                                               dw.DockingPosition = Alignment.Left;
-                                                       else if (lm.X > cb.Right - cb.Width / 3)
-                                                               dw.DockingPosition = Alignment.Right;                                                   
-                                               } else {
-                                                       getFocusedChild (lm);
-                                                       if (focusedChild != null) {
-                                                               if (lm.Y < rIn.Top + rIn.Height / 3)
-                                                                       dw.DockingPosition = Alignment.Top;
-                                                               else if (lm.Y > rIn.Bottom - rIn.Height / 3)
-                                                                       dw.DockingPosition = Alignment.Bottom;                                                                          
-                                                       }
-                                               }
-                                       }
-                                       if (Orientation == Orientation.Vertical || Children.Count == 1) {
-                                               if (lm.X > cb.Left + cb.Width / 3 && lm.X < cb.Right - cb.Width / 3) {
-                                                       if (lm.Y < cb.Top + cb.Height / 3)
-                                                               dw.DockingPosition = Alignment.Top;
-                                                       else if (lm.Y > cb.Bottom - cb.Height / 3)
-                                                               dw.DockingPosition = Alignment.Bottom;                                                  
-                                               } else {
-                                                       getFocusedChild (lm);
-                                                       if (focusedChild != null) {
-                                                               if (lm.X < rIn.Left + rIn.Width / 3)
-                                                                       dw.DockingPosition = Alignment.Left;
-                                                               else if (lm.X > rIn.Right - rIn.Width / 3)
-                                                                       dw.DockingPosition = Alignment.Right;                                                                           
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               if (curDockPos != dw.DockingPosition)
-                                       RegisterForGraphicUpdate ();
-                       }
-                       base.onMouseMove (sender, e);
-               }
-
-               protected override void onDragEnter (object sender, DragDropEventArgs e)
-               {
-                       base.onDragEnter (sender, e);
-                       RegisterForGraphicUpdate ();
-               }
-               protected override void onDragLeave (object sender, DragDropEventArgs e)
-               {
-                       DockWindow dw = e.DragSource as DockWindow;
-                       //if (dw != null)
-                       //      dw.DockingPosition = Alignment.Undefined;
-                       base.onDragLeave (sender, e);
-                       RegisterForGraphicUpdate ();
-               }
-
-               protected override void onDraw (Cairo.Context gr)
-               {
-                       gr.Save ();
-
-                       Rectangle rBack = new Rectangle (Slot.Size);
-
-                       Background.SetAsSource (gr, rBack);
-                       CairoHelpers.CairoRectangle (gr, rBack, CornerRadius);
-                       gr.Fill ();
-
-                       if (ClipToClientRect) {
-                               //clip to client zone
-                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
-                               gr.Clip ();
-                       }
-
-                       childrenRWLock.EnterReadLock ();
-
-                       foreach (Widget g in Children)
-                               g.Paint (ref gr);                       
-
-                       childrenRWLock.ExitReadLock ();
-
-
-                       if (!IsDropTarget) {
-                               gr.Restore ();
-                               return;
-                       }
-
-                       DockWindow dw = IFace.DragAndDropOperation.DragSource as DockWindow;
-                       if (dw == null)
-                               return;
-                       if (!dw.IsDocked) {
-                               Rectangle cb = ClientRectangle;
-                               double minDim = Math.Min (cb.Width, cb.Height);
-
-                               Rectangle r = rIn;
-                               if (Children.Count <= 1 || dw.DockingPosition.GetOrientation()==Orientation )
-                                       r = cb;
-
-                               switch (dw.DockingPosition) {
-                               case Alignment.Top:
-                                       gr.Rectangle (r.Left, r.Top, r.Width, r.Height * dockThresh);
-                                       break;
-                               case Alignment.Bottom:
-                                       gr.Rectangle (r.Left, r.Bottom - r.Height * dockThresh, r.Width, r.Height * dockThresh);
-                                       break;
-                               case Alignment.Left:
-                                       gr.Rectangle (r.Left, r.Top, r.Width * dockThresh, r.Height);
-                                       break;
-                               case Alignment.Right:
-                                       gr.Rectangle (r.Right - r.Width * dockThresh, r.Top, r.Width * dockThresh, r.Height);
-                                       break;
-                               case Alignment.Center:
-                                       r.Inflate ((int)Math.Ceiling (Math.Min (r.Width, r.Height) * -0.05));
-                                       gr.Rectangle (r);
-                                       break;
-                               }
-                               gr.LineWidth = 1;
-                               gr.SetSourceRGBA (0.4, 0.4, 0.9, 0.4);
-                               gr.FillPreserve ();
-                               gr.SetSourceRGBA (0.9, 0.9, 1.0, 0.8);
-                               gr.Stroke ();
-                       }
-                       gr.Restore ();  
-               }
-                       
-               public void Dock(DockWindow dw){
-                       DockStack activeStack = this;
-
-                       if (Children.Count == 1) {
-                               Orientation = dw.DockingPosition.GetOrientation ();
-                               if (Children [0] is DockWindow) {
-                                       (Children [0] as DockWindow).DockingPosition = dw.DockingPosition.GetOpposite ();
-                               }
-                       } else if (Children.Count > 0 && dw.DockingPosition.GetOrientation () != Orientation) {
-                               activeStack = new DockStack (IFace);
-                               activeStack.Orientation = dw.DockingPosition.GetOrientation ();
-                               activeStack.Width = focusedChild.Width;
-                               activeStack.Height = focusedChild.Height;
-                               int idx = Children.IndexOf (focusedChild);
-                               RemoveChild (focusedChild);
-                               focusedChild.Height = Measure.Stretched;
-                               focusedChild.Width = Measure.Stretched;
-                               InsertChild (idx, activeStack);
-                               activeStack.AddChild (focusedChild);
-                               activeStack.stretchedChild = focusedChild;
-                               if (focusedChild is DockWindow)
-                                       (focusedChild as DockWindow).DockingPosition = dw.DockingPosition.GetOpposite ();
-                               focusedChild = null;
-                       }
-
-                       Rectangle r = ClientRectangle;
-                       int vTreshold = (int)(r.Height * dockThresh);
-                       int hTreshold = (int)(r.Width * dockThresh);
-
-                       Console.WriteLine ("Docking {0} as {2} in {1}", dw.Name, activeStack.Name, dw.DockingPosition);
-                       switch (dw.DockingPosition) {
-                       case Alignment.Top:                                             
-                               dw.Height = vTreshold;
-                               dw.Width = Measure.Stretched;
-                               activeStack.InsertChild (0, dw);
-                               activeStack.InsertChild (1, new Splitter(IFace));
-                               break;
-                       case Alignment.Bottom:
-                               dw.Height = vTreshold;
-                               dw.Width = Measure.Stretched;
-                               activeStack.AddChild (new Splitter(IFace));
-                               activeStack.AddChild (dw);
-                               break;
-                       case Alignment.Left:
-                               dw.Width = hTreshold;
-                               dw.Height = Measure.Stretched;
-                               activeStack.InsertChild (0, dw);
-                               activeStack.InsertChild (1, new Splitter(IFace));
-                               break;
-                       case Alignment.Right:
-                               dw.Width = hTreshold;
-                               dw.Height = Measure.Stretched;
-                               activeStack.AddChild (new Splitter(IFace));
-                               activeStack.AddChild (dw);
-                               break;
-                       case Alignment.Center:
-                               dw.Width = dw.Height = Measure.Stretched;
-                               AddChild (dw);
-                               stretchedChild = dw;
-                               break;
-                       }
-               }
-               public void Undock (DockWindow dw){                     
-                       int idx = Children.IndexOf(dw);
-
-                       Console.WriteLine ("undocking child index: {0} ; name={1}; pos:{2} ; childcount:{3}",idx, dw.Name, dw.DockingPosition, Children.Count);
-
-                       RemoveChild(dw);
-
-                       if (Children.Count == 0)
-                               return;
-                       
-                       if (dw.DockingPosition == Alignment.Left || dw.DockingPosition == Alignment.Top) {                              
-                               RemoveChild (idx);
-                               if (stretchedChild == dw) {
-                                       stretchedChild = Children [idx];
-                                       stretchedChild.Width = stretchedChild.Height = Measure.Stretched;
-                               }
-                       } else {
-                               RemoveChild (idx - 1);
-                               if (stretchedChild == dw) {
-                                       stretchedChild = Children [idx-2];
-                                       stretchedChild.Width = stretchedChild.Height = Measure.Stretched;
-                               }
-                       }
-
-                       if (Children.Count == 1) {
-                               DockStack dsp = Parent as DockStack;
-                               if (dsp == null) {
-                                       Children [0].Width = Children [0].Height = Measure.Stretched;
-                                       return;
-                               }                               
-                               //remove level and move remaining obj to level above
-                               Widget g = Children [0];
-                               RemoveChild (g);
-                               idx = dsp.Children.IndexOf (this);
-                               dsp.RemoveChild (this);
-                               dsp.InsertChild (idx, g);
-                               g.Width = this.Width;
-                               g.Height = this.Height;
-                               if (dsp.stretchedChild == this)
-                                       dsp.stretchedChild = g;
-                               dsp.checkAlignments ();
-                       } else
-                               checkAlignments ();
-               }
-
-               internal void checkAlignments () {
-                       DockWindow dw = Children[0] as DockWindow;
-                       if (dw != null)
-                               dw.DockingPosition = (Orientation == Orientation.Horizontal ? Alignment.Left : Alignment.Top);
-                       dw = Children[Children.Count - 1] as DockWindow;
-                       if (dw != null)
-                               dw.DockingPosition = (Orientation == Orientation.Horizontal ? Alignment.Right : Alignment.Bottom);
-               }
-
-               //read next value in config string until next ';'
-               string getConfAttrib (string conf, ref int i) {
-                       int nextI = conf.Substring (i).IndexOf (';');
-                       string tmp = conf.Substring (i, nextI);
-                       i += nextI + 1;
-                       return tmp;
-               }
-               /// <summary>
-               /// Imports the config.
-               /// </summary>
-               /// <param name="conf">Conf.</param>
-               /// <param name="dataSource">Data source for the docked windows</param>
-               public void ImportConfig (string conf, object dataSource = null) {
-                       lock (IFace.UpdateMutex) {
-                               ClearChildren ();
-                               stretchedChild = null;
-                               int i = 0;
-                               Orientation = (Orientation)Enum.Parse (typeof(Orientation), getConfAttrib (conf, ref i));
-                               importConfig (conf, ref i, dataSource);
-                       }
-               }
-               public string ExportConfig () {
-                       return Orientation.ToString() + ";" + exportConfig();
-               }
-               void importConfig (string conf, ref int i, object dataSource) {                                         
-                       if (conf [i++] != '(')
-                               return;                 
-                       while (i < conf.Length - 4) {
-                               string sc = conf.Substring (i, 4);
-                               i += 4;
-                               switch (sc) {
-                               case "WIN;":
-                                       DockWindow dw = null;
-                                       string wName = getConfAttrib (conf, ref i);
-                                       try {
-                                               dw = IFace.CreateInstance (wName) as DockWindow;        
-                                       } catch {
-                                               dw = new DockWindow (IFace);
-                                       }
-
-                                       dw.Name = wName;
-                                       dw.Width = Measure.Parse (getConfAttrib (conf, ref i));
-                                       dw.Height = Measure.Parse (getConfAttrib (conf, ref i));
-                                       dw.DockingPosition = (Alignment)Enum.Parse (typeof(Alignment), getConfAttrib (conf, ref i));
-                                       dw.savedSlot = Rectangle.Parse (getConfAttrib (conf, ref i));
-                                       dw.wasResizable = Boolean.Parse (getConfAttrib (conf, ref i));
-
-                                       dw.IsDocked = true;
-                                       dw.DataSource = dataSource;
-                                       this.AddChild (dw);
-
-                                       break;
-                               case "STK;":
-                                       DockStack ds = new DockStack (IFace);
-                                       ds.Width = Measure.Parse (getConfAttrib (conf, ref i));
-                                       ds.Height = Measure.Parse (getConfAttrib (conf, ref i));
-                                       ds.Orientation = (Orientation)Enum.Parse (typeof(Orientation), getConfAttrib (conf, ref i));
-
-                                       this.AddChild (ds);
-
-                                       ds.importConfig (conf, ref i, dataSource);
-                                       break;
-                               case "SPL;":
-                                       Splitter sp = new Splitter (IFace);
-                                       sp.Width = Measure.Parse (getConfAttrib (conf, ref i));
-                                       sp.Height = Measure.Parse (getConfAttrib (conf, ref i));
-                                       sp.Thickness = int.Parse (getConfAttrib (conf, ref i));
-                                       this.AddChild (sp);
-                                       break;
-                               }
-                               char nextC = conf [i++];
-                               if (nextC == ')')
-                                       break;
-                       }
-               }
-               string exportConfig () {
-                       StringBuilder tmp = new StringBuilder("(");
-
-                       for (int i = 0; i < Children.Count; i++) {
-                               if (Children [i] is DockWindow) {
-                                       DockWindow dw = Children [i] as DockWindow;
-                                       tmp.Append (string.Format("WIN;{0};{1};{2};{3};{4};{5};",dw.Name, dw.Width, dw.Height, dw.DockingPosition, dw.savedSlot, dw.wasResizable));
-                               } else if (Children [i] is DockStack) {
-                                       DockStack ds = Children [i] as DockStack;
-                                       tmp.Append (string.Format("STK;{0};{1};{2};{3}", ds.Width, ds.Height, ds.Orientation, ds.exportConfig()));
-                               } else if (Children [i] is Splitter) {
-                                       Splitter sp = Children [i] as Splitter;
-                                       tmp.Append (string.Format("SPL;{0};{1};{2};", sp.Width, sp.Height, sp.Thickness));
-                               }                                       
-                               if (i < Children.Count - 1)
-                                       tmp.Append ("|");                               
-                       }
-
-                       tmp.Append (")");
-                       return tmp.ToString ();
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/DockWindow.cs b/Crow/src/GraphicObjects/DockWindow.cs
deleted file mode 100644 (file)
index 4be23ad..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-//
-// DockingView.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.Xml.Serialization;
-
-namespace Crow
-{
-       public class DockWindow : Window
-       {
-               #region CTOR
-               public DockWindow () {}
-               public DockWindow (Interface iface) : base (iface) {}
-               #endregion
-
-               int undockThreshold = 10;
-               bool isDocked = false;
-               Alignment docking = Alignment.Undefined;
-
-               Point undockingMousePosOrig; //mouse pos when docking was donne, use for undocking on mouse move
-               internal Rectangle savedSlot;   //last undocked slot recalled when view is undocked
-               internal bool wasResizable;
-
-               public bool IsDocked {
-                       get { return isDocked; }
-                       set {
-                               if (isDocked == value)
-                                       return;
-                               isDocked = value;
-                               NotifyValueChanged ("IsDocked", isDocked);
-                               NotifyValueChanged ("IsFloating", !isDocked);
-                       }
-               }
-               [XmlIgnore] public bool IsFloating { get { return !isDocked; }}
-
-               public Alignment DockingPosition {
-                       get { return docking; }
-                       set {
-                               if (docking == value)
-                                       return;
-                               docking = value;
-                               NotifyValueChanged ("DockingPosition", DockingPosition);
-                       }
-               }
-               public override bool PointIsIn (ref Point m)
-               {                       
-                       if (!base.PointIsIn(ref m))
-                               return false;
-
-                       Group p = Parent as Group;
-                       if (p != null) {
-                               lock (p.Children) {
-                                       for (int i = p.Children.Count - 1; i >= 0; i--) {
-                                               if (p.Children [i] == this)
-                                                       break;
-                                               if (p.Children [i].IsDragged)
-                                                       continue;
-                                               if (p.Children [i].Slot.ContainsOrIsEqual (m)) {                                                
-                                                       return false;
-                                               }
-                                       }
-                               }
-                       }
-                       return Slot.ContainsOrIsEqual(m);
-               }
-
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-//                     if (this.HasFocus && e.Mouse.IsButtonDown (MouseButton.Left) && IsDocked) {
-//                             if (Math.Abs (e.Position.X - undockingMousePosOrig.X) > 10 ||
-//                                 Math.Abs (e.Position.X - undockingMousePosOrig.X) > 10)
-//                                     Undock ();
-//                     }
-
-                       if (this.HasFocus && e.Mouse.IsButtonDown (MouseButton.Left) && IsDocked)
-                               CheckUndock (e.Position);
-
-                       base.onMouseMove (sender, e);
-               }
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       e.Handled = true;
-                       base.onMouseDown (sender, e);
-
-                       if (this.HasFocus && IsDocked && e.Button == MouseButton.Left)
-                               undockingMousePosOrig = e.Position;
-               }
-               public bool CheckUndock (Point mousePos) {
-                       //if (DockingPosition == Alignment.Center)
-                       //      return false;
-                       Console.WriteLine ($"{mousePos.X},{mousePos.Y}");
-                       if (Math.Abs (mousePos.X - undockingMousePosOrig.X) < undockThreshold ||
-                           Math.Abs (mousePos.X - undockingMousePosOrig.X) < undockThreshold)
-                               return false;
-                       Undock ();
-                       return true;
-               }
-
-               protected override void onStartDrag (object sender, DragDropEventArgs e)
-               {
-                       base.onStartDrag (sender, e);
-
-                       undockingMousePosOrig = IFace.Mouse.Position;
-               }
-               protected override void onDrop (object sender, DragDropEventArgs e)
-               {
-                       if (!isDocked && DockingPosition != Alignment.Undefined && e.DropTarget is DockStack)
-                               Dock (e.DropTarget as DockStack);
-                       base.onDrop (sender, e);
-               }
-               public void Undock () {
-                       lock (IFace.UpdateMutex) {
-                               DockStack ds = Parent as DockStack;
-                               ds.Undock (this);
-
-                               IFace.AddWidget (this);
-
-                               Left = savedSlot.Left;
-                               Top = savedSlot.Top;
-                               Width = savedSlot.Width;
-                               Height = savedSlot.Height;
-
-                               IsDocked = false;
-                               DockingPosition = Alignment.Undefined;
-                               Resizable = wasResizable;
-                       }
-               }
-
-               public void Dock (DockStack target){
-                       lock (IFace.UpdateMutex) {
-                               IsDocked = true;
-                               //undockingMousePosOrig = lastMousePos;
-                               savedSlot = this.LastPaintedSlot;
-                               wasResizable = Resizable;
-                               Resizable = false;
-                               LastSlots = LastPaintedSlot = Slot = default(Rectangle);
-                               Left = Top = 0;
-
-                               IFace.RemoveWidget (this);
-
-                               target.Dock (this);
-                       }
-               }
-
-               protected override void close ()
-               {
-                       if (isDocked)
-                               Undock ();
-                       base.close ();
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/EnumSelector.cs b/Crow/src/GraphicObjects/EnumSelector.cs
deleted file mode 100644 (file)
index 932e90e..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.ComponentModel;
-
-namespace Crow
-{
-       /// <summary>
-       /// Convenient widget for selecting value from enum
-       /// </summary>
-       public class EnumSelector : GenericStack
-       {
-               #region CTOR
-               protected EnumSelector () : base(){}
-               public EnumSelector (Interface iface) : base(iface){}
-               #endregion
-
-               #region private fields
-               Enum enumValue;
-               Type enumType;
-               #endregion
-
-               #region public properties
-               /// <summary>
-               /// use to define the colors of the 3d border
-               /// </summary>
-               [DefaultValue(null)]
-               public virtual Enum EnumValue {
-                       get { return enumValue; }
-                       set {
-                               if (enumValue == value)
-                                       return;
-
-                               enumValue = value;
-
-                               if (enumValue != null) {
-                                       if (enumType != enumValue.GetType ()) {
-                                               ClearChildren ();
-                                               enumType = enumValue.GetType ();
-                                               foreach (string en in enumType.GetEnumNames ()) {
-                                                       RadioButton rb = new RadioButton (IFace);
-                                                       rb.Caption = en;
-                                                       if (enumValue.ToString() == en)
-                                                               rb.IsChecked = true;
-                                                       rb.Checked += (sender, e) => (((RadioButton)sender).Parent as EnumSelector).EnumValue = (Enum)Enum.Parse (enumType, (sender as RadioButton).Caption);
-                                                       AddChild (rb);
-                                                       RegisterForLayouting (LayoutingType.All);
-                                               }
-                                       }
-                               } else 
-                                       ClearChildren ();
-
-                               NotifyValueChanged ("EnumValue", enumValue);
-                               RegisterForRedraw ();
-                       }
-               }
-               #endregion
-
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Expandable.cs b/Crow/src/GraphicObjects/Expandable.cs
deleted file mode 100644 (file)
index 3a480b2..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// Expandable.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.ComponentModel;
-using System.Xml.Serialization;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated control whose content can be hidden and shown on demand
-       /// </summary>
-    public class Expandable : TemplatedContainer
-    {
-               #region CTOR
-               protected Expandable() : base(){}
-               public Expandable (Interface iface) : base(iface){}
-               #endregion
-
-               #region Private fields
-               bool _isExpanded;
-               string image;
-               #endregion
-
-               #region Event Handlers
-               /// <summary>
-               /// Occurs when control is expanded.
-               /// </summary>
-               public event EventHandler Expand;
-               /// <summary>
-               /// Occurs when control is collapsed.
-               /// </summary>
-               public event EventHandler Collapse;
-               #endregion
-
-               public BooleanTestOnInstance GetIsExpandable;
-
-               /// <summary>
-               /// mouse click event handler for easy expand triggering in IML
-               /// </summary>
-               public void onClickForExpand (object sender, MouseButtonEventArgs e)
-               {
-                       IsExpanded = !IsExpanded;
-               }
-
-               #region Public properties
-               [DefaultValue("#Crow.Icons.expandable.svg")]
-               public string Image {
-                       get { return image; }
-                       set {
-                               if (image == value)
-                                       return;
-                               image = value;
-                               NotifyValueChanged ("Image", image);
-                       }
-               }
-               [DefaultValue(false)]
-        public bool IsExpanded
-        {
-                       get { return _isExpanded; }
-            set
-            {
-                               if (value == _isExpanded)
-                                       return;
-
-                               _isExpanded = value;
-
-                               bool isExp = IsExpandable;
-                               NotifyValueChanged ("IsExpandable", isExp);
-                               if (!isExp)
-                                       _isExpanded = false;
-
-                               NotifyValueChanged ("IsExpanded", _isExpanded);
-
-                               if (_isExpanded)
-                                       onExpand (this, null);
-                               else
-                                       onCollapse (this, null);
-            }
-        }
-               [XmlIgnore]public bool IsExpandable {
-                       get {
-                               try {
-                                       return GetIsExpandable == null ? true : GetIsExpandable (this);
-                               } catch (Exception ex) {
-                                       System.Diagnostics.Debug.WriteLine ("Not Expandable error: " + ex.ToString ());
-                                       return false;
-                               }
-                       }
-               }
-               #endregion
-
-               public virtual void onExpand(object sender, EventArgs e)
-               {
-                       if (_contentContainer != null)
-                               _contentContainer.Visible = true;
-
-                       Expand.Raise (this, e);
-               }
-               public virtual void onCollapse(object sender, EventArgs e)
-               {
-                       if (_contentContainer != null)
-                               _contentContainer.Visible = false;
-
-                       Collapse.Raise (this, e);
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/FileDialog.cs b/Crow/src/GraphicObjects/FileDialog.cs
deleted file mode 100644 (file)
index db66ae9..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-//
-// FileDialog.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.Xml.Serialization;
-using System.ComponentModel;
-using System.IO;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text.RegularExpressions;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated control for selecting files
-       /// </summary>
-       public class FileDialog: Window
-       {
-               #region CTOR
-               protected FileDialog() : base(){}
-               public FileDialog (Interface iface) : base(iface){}
-               #endregion
-
-               string searchPattern, curDir, _selectedFile, _selectedDir;
-               bool showHidden, showFiles;
-
-               #region events
-               public event EventHandler OkClicked;
-               #endregion
-
-               public string SelectedFileFullPath {
-                       get { return Path.Combine (SelectedDirectory, SelectedFile); }
-               }
-               [DefaultValue("/home")]
-               public virtual string CurrentDirectory {
-                       get { return curDir; }
-                       set {
-                               if (curDir == value)
-                                       return;
-                               curDir = value;
-                               NotifyValueChanged ("CurrentDirectory", curDir);
-                               SelectedDirectory = curDir;
-                       }
-               }
-
-               [DefaultValue("*")]
-               public virtual string SearchPattern {
-                       get { return searchPattern; }
-                       set {
-                               if (searchPattern == value)
-                                       return;
-                               searchPattern = value;
-                               NotifyValueChanged ("SearchPattern", searchPattern);
-
-                       }
-               }
-               [DefaultValue(false)]
-               public virtual bool ShowHidden {
-                       get { return showHidden; }
-                       set {
-                               if (showHidden == value)
-                                       return;
-                               showHidden = value;
-                               NotifyValueChanged ("ShowHidden", showHidden);
-                       }
-               }
-               [DefaultValue(true)]
-               public virtual bool ShowFiles {
-                       get { return showFiles; }
-                       set {
-                               if (showFiles == value)
-                                       return;
-                               showFiles = value;
-                               NotifyValueChanged ("ShowFiles", showFiles);
-                       }
-               }
-               public string SelectedFile {
-                       get { return _selectedFile; }
-                       set {
-                               if (value == _selectedFile)
-                                       return;
-                               _selectedFile = value;
-                               NotifyValueChanged ("SelectedFile", _selectedFile);
-                       }
-               }
-               public string SelectedDirectory {
-                       get { return _selectedDir; }
-                       set {
-                               if (value == _selectedDir)
-                                       return;
-                               _selectedDir = value;
-                               NotifyValueChanged ("SelectedDirectory", _selectedDir);
-                       }
-               }
-
-               public void onFVSelectedItemChanged (object sender, SelectionChangeEventArgs e){
-                       if (e.NewValue != null) {
-                               if (File.GetAttributes (e.NewValue.ToString ()).HasFlag (FileAttributes.Directory)) {
-                                       SelectedDirectory = e.NewValue.ToString ();
-                                       SelectedFile = "";
-                               } else {
-                                       SelectedDirectory = Path.GetDirectoryName (e.NewValue.ToString ());
-                                       SelectedFile = Path.GetFileName (e.NewValue.ToString ());
-                               }
-                       }
-               }
-               public void onDVSelectedItemChanged (object sender, SelectionChangeEventArgs e){
-                       if (e.NewValue != null)
-                               SelectedDirectory = e.NewValue.ToString();
-               }
-               public void goUpDirClick (object sender, MouseButtonEventArgs e){
-                       string root = Directory.GetDirectoryRoot(CurrentDirectory);
-                       if (CurrentDirectory == root)
-                               return;
-                       CurrentDirectory = Directory.GetParent(CurrentDirectory).FullName;
-               }
-               void onFileSelect(object sender, MouseButtonEventArgs e){
-                       if (string.IsNullOrEmpty (SelectedFile))
-                               CurrentDirectory = SelectedDirectory;
-                       else {
-                               OkClicked.Raise (this, null);
-                               IFace.DeleteWidget (this);
-                       }
-               }
-               void onCancel(object sender, MouseButtonEventArgs e){
-                       IFace.DeleteWidget (this);
-               }
-
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/GenericStack.cs b/Crow/src/GraphicObjects/GenericStack.cs
deleted file mode 100644 (file)
index 5189748..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-//
-// GenericStack.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.ComponentModel;
-using System.Diagnostics;
-using System.Xml.Serialization;
-using System;
-using System.Linq;
-
-namespace Crow
-{
-       /// <summary>
-       /// group container that stacked its children horizontally or vertically
-       /// </summary>
-       public class GenericStack : Group
-    {
-               #region CTOR
-               protected GenericStack() : base(){}
-               public GenericStack(Interface iface) : base(iface){}
-               #endregion
-
-               #region Private fields
-        int _spacing;
-        Orientation _orientation;
-               #endregion
-
-               #region Public Properties
-        [DefaultValue(2)]
-        public int Spacing
-        {
-                       get { return _spacing; }
-            set { 
-                               if (_spacing == value)
-                                       return;
-                               _spacing = value; 
-                               NotifyValueChanged ("Spacing", Spacing);
-                               RegisterForLayouting (LayoutingType.Sizing|LayoutingType.ArrangeChildren);
-                       }
-        }
-        [DefaultValue(Orientation.Horizontal)]
-        public virtual Orientation Orientation
-        {
-            get { return _orientation; }
-            set { _orientation = value; }
-        }
-               #endregion
-
-               #region GraphicObject Overrides
-               public override bool ArrangeChildren { get { return true; } }
-               public override void ChildrenLayoutingConstraints (ref LayoutingType layoutType)
-               {
-                       //Prevent child repositionning in the direction of stacking
-                       if (Orientation == Orientation.Horizontal)
-                               layoutType &= (~LayoutingType.X);
-                       else
-                               layoutType &= (~LayoutingType.Y);                       
-               }
-               protected override int measureRawSize (LayoutingType lt)
-               {
-                       int totSpace = Math.Max(0, Spacing * (Children.Count (c => c.Visible) - 1));
-                       if (lt == LayoutingType.Width) {
-                               if (Orientation == Orientation.Horizontal)
-                                       return contentSize.Width + totSpace + 2 * Margin;
-                       }else if (Orientation == Orientation.Vertical)
-                               return contentSize.Height + totSpace + 2 * Margin;                                                      
-                       
-                       return base.measureRawSize (lt);
-               }
-               public virtual void ComputeChildrenPositions()
-               {
-                       int d = 0;
-                       if (Orientation == Orientation.Horizontal) {
-                               foreach (Widget c in Children) {
-                                       if (!c.Visible)
-                                               continue;
-                                       c.Slot.X = d;
-                                       d += c.Slot.Width + Spacing;
-                               }
-                       } else {
-                               foreach (Widget c in Children) {
-                                       if (!c.Visible)
-                                               continue;                                       
-                                       c.Slot.Y = d;
-                                       d += c.Slot.Height + Spacing;
-                               }
-                       }
-                       IsDirty = true;
-               }
-               Widget stretchedGO = null;
-               public override bool UpdateLayout (LayoutingType layoutType)
-        {
-                       RegisteredLayoutings &= (~layoutType);
-
-                       if (layoutType == LayoutingType.ArrangeChildren) {
-                               //allow 1 child to have size to 0 if stack has fixed or streched size policy,
-                               //this child will occupy remaining space
-                               //if stack size policy is Fit, no child may have stretch enabled
-                               //in the direction of stacking.
-                               ComputeChildrenPositions ();
-
-                               //if no layouting remains in queue for item, registre for redraw
-                               if (RegisteredLayoutings == LayoutingType.None && IsDirty)
-                                       IFace.EnqueueForRepaint (this);
-
-                               return true;
-                       }
-
-                       return base.UpdateLayout(layoutType);
-        }
-
-               void adjustStretchedGo (LayoutingType lt){
-                       if (stretchedGO == null)
-                               return;
-                       if (lt == LayoutingType.Width) {
-                               int newW = Math.Max (
-                                                  this.ClientRectangle.Width - contentSize.Width - Spacing * (Children.Count - 1),
-                                                  stretchedGO.MinimumSize.Width);
-                               if (stretchedGO.MaximumSize.Width > 0)
-                                       newW = Math.Min (newW, stretchedGO.MaximumSize.Width);
-                               if (newW != stretchedGO.Slot.Width) {                                                   
-                                       stretchedGO.Slot.Width = newW;
-                                       stretchedGO.IsDirty = true;
-                                       #if DEBUG_LAYOUTING
-                               Debug.WriteLine ("\tAdjusting Width of " + stretchedGO.ToString());
-                                       #endif
-                                       stretchedGO.LayoutChanged -= OnChildLayoutChanges;
-                                       stretchedGO.OnLayoutChanges (LayoutingType.Width);
-                                       stretchedGO.LayoutChanged += OnChildLayoutChanges;
-                                       stretchedGO.LastSlots.Width = stretchedGO.Slot.Width;
-                               }
-                       } else {
-                               int newH = Math.Max (
-                                       this.ClientRectangle.Height - contentSize.Height - Spacing * (Children.Count - 1),
-                                       stretchedGO.MinimumSize.Height);
-                               if (stretchedGO.MaximumSize.Height > 0)
-                                       newH = Math.Min (newH, stretchedGO.MaximumSize.Height);
-                               if (newH != stretchedGO.Slot.Height) {
-                                       stretchedGO.Slot.Height = newH;
-                                       stretchedGO.IsDirty = true;
-                                       #if DEBUG_LAYOUTING
-                                       Debug.WriteLine ("\tAdjusting Height of " + stretchedGO.ToString());
-                                       #endif
-                                       stretchedGO.LayoutChanged -= OnChildLayoutChanges;
-                                       stretchedGO.OnLayoutChanges (LayoutingType.Height);
-                                       stretchedGO.LayoutChanged += OnChildLayoutChanges;
-                                       stretchedGO.LastSlots.Height = stretchedGO.Slot.Height;
-                               }                               
-                       }
-               }
-
-               public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
-               {
-                       Widget go = sender as Widget;
-                       //Debug.WriteLine ("child layout change: " + go.LastSlots.ToString() + " => " + go.Slot.ToString());
-                       switch (arg.LayoutType) {
-                       case LayoutingType.Width:
-                               if (Orientation == Orientation.Horizontal) {
-                                       if (go.Width == Measure.Stretched) {
-                                               if (stretchedGO == null && Width != Measure.Fit)
-                                                       stretchedGO = go;
-                                               else if (stretchedGO != go) {
-                                                       go.Slot.Width = 0;
-                                                       go.Width = Measure.Fit;
-                                                       return;
-                                               }
-                                       } else
-                                               contentSize.Width += go.Slot.Width - go.LastSlots.Width;
-
-                                       adjustStretchedGo (LayoutingType.Width);                                        
-                                       
-                                       if (Width == Measure.Fit)
-                                               this.RegisterForLayouting (LayoutingType.Width);
-                                       
-                                       this.RegisterForLayouting (LayoutingType.ArrangeChildren);
-                                       return;
-                               }
-                               break;
-                       case LayoutingType.Height:
-                               if (Orientation == Orientation.Vertical) {
-                                       if (go.Height == Measure.Stretched) {
-                                               if (stretchedGO == null && Height != Measure.Fit)
-                                                       stretchedGO = go;
-                                               else if (stretchedGO != go){
-                                                       go.Slot.Height = 0;
-                                                       go.Height = Measure.Fit;
-                                                       return;
-                                               }
-                                       } else
-                                               contentSize.Height += go.Slot.Height - go.LastSlots.Height;
-                                       
-                                       adjustStretchedGo (LayoutingType.Height);
-
-                                       if (Height == Measure.Fit)
-                                               this.RegisterForLayouting (LayoutingType.Height);
-
-                                       this.RegisterForLayouting (LayoutingType.ArrangeChildren);
-                                       return;
-                               }
-                               break;
-                       }
-                       base.OnChildLayoutChanges (sender, arg);
-               }
-               #endregion
-
-       public override void RemoveChild (Widget child)
-               {
-                       if (child != stretchedGO) {
-                               if (Orientation == Orientation.Horizontal)
-                                       contentSize.Width -= child.LastSlots.Width;
-                               else 
-                                       contentSize.Height -= child.LastSlots.Height;                           
-                       }
-                       base.RemoveChild (child);
-                       if (child == stretchedGO) {
-                               stretchedGO = null;
-                               RegisterForLayouting (LayoutingType.Sizing);
-                       }else if (Orientation == Orientation.Horizontal)                                
-                               adjustStretchedGo (LayoutingType.Width);
-                       else                            
-                               adjustStretchedGo (LayoutingType.Height);                       
-               }
-
-               public override void ClearChildren ()
-               {
-                       base.ClearChildren ();
-                       stretchedGO = null;
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/GraduatedSlider.cs b/Crow/src/GraphicObjects/GraduatedSlider.cs
deleted file mode 100644 (file)
index 71bbff1..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// GraduatedSlider.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.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crow.Cairo;
-using System.Xml.Serialization;
-
-namespace Crow
-{
-       [DesignIgnore]
-       public class GraduatedSlider : Slider
-    {     
-               #region CTOR
-               protected GraduatedSlider() : base(){}
-               public GraduatedSlider(Interface iface) : base(iface)
-               {}
-//             public GraduatedSlider(double minimum, double maximum, double step)
-//            : base()
-//        {
-//                     Minimum = minimum;
-//                     Maximum = maximum;
-//                     SmallIncrement = step;
-//                     LargeIncrement = step * 5;
-//        }
-               #endregion
-
-               protected override void DrawGraduations(Context gr, PointD pStart, PointD pEnd)
-               {
-                       Rectangle r = ClientRectangle;
-                       Foreground.SetAsSource (gr);
-
-                       gr.LineWidth = 2;
-                       gr.MoveTo(pStart);
-                       gr.LineTo(pEnd);
-
-                       gr.Stroke();
-                       gr.LineWidth = 1;
-
-                       double sst = unity * SmallIncrement;
-                       double bst = unity * LargeIncrement;
-
-
-                       PointD vBar = new PointD(0, sst);
-                       for (double x = Minimum; x <= Maximum - Minimum; x += SmallIncrement)
-                       {
-                               double lineLength = r.Height / 3;
-                               if (x % LargeIncrement != 0)
-                                       lineLength /= 3;
-                               PointD p = new PointD(pStart.X + x * unity, pStart.Y);
-                               gr.MoveTo(p);
-                               gr.LineTo(new PointD(p.X, p.Y + lineLength));
-                       }
-                       gr.Stroke();
-               }
-    }
-}
diff --git a/Crow/src/GraphicObjects/Grid.cs b/Crow/src/GraphicObjects/Grid.cs
deleted file mode 100644 (file)
index ad776bd..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-//
-// Grid.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.Diagnostics;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       /// <summary>
-       /// Simple grid container
-       /// Allow symetric placement of children on a grid,
-       /// excedental child (above grid sizing) are ignored
-       /// and invisible child keep their place in the grid
-       /// </summary>
-    public class Grid : Group
-    {
-               #region CTOR
-               protected Grid () : base(){}
-               public Grid(Interface iface) : base(iface)
-               {            
-               }
-               #endregion
-
-               #region Private fields
-        int _spacing;
-               int _columnCount;
-               int _rowCount;
-               #endregion
-
-               #region Public Properties
-        [DefaultValue(2)]
-        public int Spacing
-        {
-                       get { return _spacing; }
-            set { _spacing = value; }
-        }
-        [DefaultValue(2)]
-        public virtual int ColumnCount
-        {
-            get { return _columnCount; }
-            set { 
-                               if (_columnCount == value)
-                                       return;
-
-                               _columnCount = value; 
-
-                               NotifyValueChanged ("ColumnCount", ColumnCount);
-                               this.RegisterForLayouting (LayoutingType.ArrangeChildren);
-                       }
-        }
-               [DefaultValue(2)]
-               public virtual int RowCount
-               {
-                       get { return _rowCount; }
-                       set { 
-                               if (_rowCount == value)
-                                       return;
-
-                               _rowCount = value; 
-
-                               NotifyValueChanged ("RowCount", RowCount);
-                               this.RegisterForLayouting (LayoutingType.ArrangeChildren);
-                       }
-               }
-               public virtual int CaseWidth {
-                       get { return (Slot.Width - (ColumnCount - 1) * Spacing) / ColumnCount; }
-               }
-               public virtual int CaseHeight {
-                       get { return (Slot.Height - (RowCount - 1) * Spacing) / RowCount; }
-               }
-
-               #endregion
-
-               #region GraphicObject Overrides
-//             protected override Size measureRawSize ()
-//             {
-//                     Size tmp = new Size ();
-//
-//                     foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) {
-//                             tmp.Width = Math.Max (tmp.Width, c.Slot.Width);
-//                             tmp.Height = Math.Max (tmp.Height, c.Slot.Height);
-//                     }
-//
-//                     tmp.Width *= (ColumnCount - 1) * Spacing / ColumnCount;;
-//                     tmp.Height *= (RowCount - 1) * Spacing / RowCount;
-//                     tmp.Width += 2 * Margin;
-//                     tmp.Height += 2 * Margin;
-//
-//                     return tmp;
-//             }
-               public override void ChildrenLayoutingConstraints (ref LayoutingType layoutType)
-               {
-                       //Prevent child repositionning
-                       layoutType &= (~LayoutingType.Positioning);
-               }
-               public override bool ArrangeChildren { get { return true; } }
-               public virtual void ComputeChildrenPositions()
-               {
-                       int slotWidth = CaseWidth;
-                       int slotHeight = CaseHeight;
-                       for (int curY = 0; curY < RowCount; curY++) {
-                               for (int curX = 0; curX < ColumnCount; curX++) {
-                                       int idx = curY * ColumnCount + curX;
-                                       if (idx >= Children.Count)
-                                               return;
-                                       Widget c = Children [idx];
-                                       if (!c.Visible)
-                                               continue;
-                                       c.Slot.X = curX * (slotWidth + Spacing);
-                                       c.Slot.Y = curY * (slotHeight + Spacing);
-                                       //c.Slot.Width = slotWidth;
-                                       //c.Slot.Height = slotHeight;
-                               }
-                       }
-                       IsDirty = true;
-               }
-               public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
-               {
-                       //base.OnChildLayoutChanges (sender, arg);
-               }
-
-               public override bool UpdateLayout (LayoutingType layoutType)
-               {
-                       RegisteredLayoutings &= (~layoutType);
-
-                       if (layoutType == LayoutingType.ArrangeChildren) {                              
-
-                               ComputeChildrenPositions ();
-
-                               //if no layouting remains in queue for item, registre for redraw
-                               if (RegisteredLayoutings == LayoutingType.None && IsDirty)
-                                       IFace.EnqueueForRepaint (this);
-                               
-                               return true;
-                       }
-
-                       return base.UpdateLayout(layoutType);
-               }
-               #endregion
-
-    
-       }
-}
diff --git a/Crow/src/GraphicObjects/Group.cs b/Crow/src/GraphicObjects/Group.cs
deleted file mode 100644 (file)
index a0ae35b..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-//
-// Group.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.Collections.Generic;
-using System.ComponentModel;
-using System.Xml.Serialization;
-using Crow.Cairo;
-using System.Diagnostics;
-using System.Reflection;
-using System.Threading;
-
-
-namespace Crow
-{
-       public class Group : Widget
-    {
-               #if DESIGN_MODE
-               public override bool FindByDesignID(string designID, out Widget go){
-                       go = null;
-                       if (base.FindByDesignID (designID, out go))
-                               return true;
-                       childrenRWLock.EnterReadLock ();
-                       foreach (Widget w in Children) {
-                               if (!w.FindByDesignID (designID, out go))
-                                       continue;
-                               childrenRWLock.ExitReadLock ();
-                               return true;
-                       }
-                       childrenRWLock.ExitReadLock ();
-                       return false;
-               }
-               public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem)
-               {
-                       if (this.design_isTGItem)
-                               return;
-                       base.getIML (doc, parentElem);
-                       foreach (Widget g in Children) {
-                               g.getIML (doc, parentElem.LastChild);   
-                       }
-               }
-               #endif
-
-               protected ReaderWriterLockSlim childrenRWLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
-
-               #region CTOR
-               public Group () : base() {}
-               public Group(Interface iface) : base(iface){}
-               #endregion
-
-               #region EVENT HANDLERS
-               public event EventHandler<EventArgs> ChildrenCleared;
-               #endregion
-
-               internal Widget largestChild = null;
-               internal Widget tallestChild = null;
-
-        bool _multiSelect = false;
-               List<Widget> children = new List<Widget>();
-
-        public virtual List<Widget> Children {
-                       get { return children; }
-               }
-               [DefaultValue(false)]
-        public bool MultiSelect
-        {
-            get { return _multiSelect; }
-            set { _multiSelect = value; }
-        }
-               public virtual void AddChild(Widget g){
-                       childrenRWLock.EnterWriteLock();
-
-                       g.Parent = this;
-                       Children.Add (g);
-
-                       childrenRWLock.ExitWriteLock();
-
-                       g.RegisteredLayoutings = LayoutingType.None;
-                       g.LayoutChanged += OnChildLayoutChanges;
-                       g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
-               }
-        public virtual void RemoveChild(Widget child)
-               {
-                       child.LayoutChanged -= OnChildLayoutChanges;
-                       //check if HoverWidget is removed from Tree
-                       if (IFace.HoverWidget != null) {
-                               if (this.Contains (IFace.HoverWidget))
-                                       IFace.HoverWidget = null;
-                       }
-
-                       childrenRWLock.EnterWriteLock ();
-
-                       Children.Remove(child);
-                       child.Parent = null;
-
-                       childrenRWLock.ExitWriteLock ();
-
-                       if (child == largestChild && Width == Measure.Fit)
-                               searchLargestChild ();
-                       if (child == tallestChild && Height == Measure.Fit)
-                               searchTallestChild ();
-
-                       this.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
-
-               }
-        public virtual void DeleteChild(Widget child)
-               {
-                       RemoveChild (child);
-                       child.Dispose ();
-        }
-               public virtual void InsertChild (int idx, Widget g) {
-                       childrenRWLock.EnterWriteLock ();
-                               
-                       g.Parent = this;
-                       Children.Insert (idx, g);
-
-                       childrenRWLock.ExitWriteLock ();
-
-                       g.RegisteredLayoutings = LayoutingType.None;
-                       g.LayoutChanged += OnChildLayoutChanges;
-                       g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
-               }
-               public virtual void RemoveChild (int idx) {
-                       RemoveChild (children[idx]);
-               }
-               public virtual void DeleteChild (int idx) {
-                       DeleteChild (children[idx]);
-               }
-               public virtual void ClearChildren()
-               {
-                       childrenRWLock.EnterWriteLock ();
-
-                       while (Children.Count > 0) {
-                               Widget g = Children [Children.Count - 1];
-                               g.LayoutChanged -= OnChildLayoutChanges;
-                               Children.RemoveAt (Children.Count - 1);
-                               g.Dispose ();
-                       }
-
-                       childrenRWLock.ExitWriteLock ();
-
-                       resetChildrenMaxSize ();
-
-                       this.RegisterForLayouting (LayoutingType.Sizing);
-                       ChildrenCleared.Raise (this, new EventArgs ());
-               }
-               public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
-               {
-                       base.OnDataSourceChanged (this, e);
-
-                       childrenRWLock.EnterReadLock ();
-                       foreach (Widget g in Children) {
-                               if (g.localDataSourceIsNull & g.localLogicalParentIsNull)
-                                       g.OnDataSourceChanged (g, e);   
-                       }
-                       childrenRWLock.ExitReadLock ();
-               }
-
-               public void putWidgetOnTop(Widget w)
-               {
-                       if (Children.Contains(w))
-                       {
-                               childrenRWLock.EnterWriteLock ();
-
-                               Children.Remove (w);
-                               Children.Add (w);
-
-                               childrenRWLock.ExitWriteLock ();
-                       }
-               }
-               public void putWidgetOnBottom(Widget w)
-               {
-                       if (Children.Contains(w))
-                       {
-                               childrenRWLock.EnterWriteLock ();
-
-                               Children.Remove (w);
-                               Children.Insert (0, w);
-
-                               childrenRWLock.ExitWriteLock ();
-                       }
-               }
-
-               #region GraphicObject overrides
-
-               public override Widget FindByName (string nameToFind)
-               {
-                       if (Name == nameToFind)
-                               return this;
-                       Widget tmp = null;
-
-                       childrenRWLock.EnterReadLock ();
-
-                       foreach (Widget w in Children) {
-                               tmp = w.FindByName (nameToFind);
-                               if (tmp != null)
-                                       break;
-                       }
-
-                       childrenRWLock.ExitReadLock ();
-
-                       return tmp;
-               }
-               public override bool Contains (Widget goToFind)
-               {
-                       foreach (Widget w in Children) {
-                               if (w == goToFind)
-                                       return true;
-                               if (w.Contains (goToFind))
-                                       return true;
-                       }
-                       return false;
-               }
-               protected override int measureRawSize (LayoutingType lt)
-               {
-                       if (Children.Count > 0) {
-                               if (lt == LayoutingType.Width) {
-                                       if (largestChild == null)
-                                               searchLargestChild ();
-                                       if (largestChild == null) {
-                                               //if still null, not possible to determine a width
-                                               //because all children are stretched, force first one to fit
-                                               Children [0].Width = Measure.Fit;
-                                               return -1;//cancel actual sizing to let child computation take place
-                                       }
-                               } else {
-                                       if (tallestChild == null)
-                                               searchTallestChild ();
-                                       if (tallestChild == null) {
-                                               Children [0].Height = Measure.Fit;
-                                               return -1;
-                                       }
-                               }
-                       }
-                       return base.measureRawSize (lt);
-               }
-
-               public override void OnLayoutChanges (LayoutingType layoutType)
-               {
-                       base.OnLayoutChanges (layoutType);
-
-                       childrenRWLock.EnterReadLock ();
-                       //position smaller objects in group when group size is fit
-                       switch (layoutType) {
-                       case LayoutingType.Width:
-                               foreach (Widget c in Children) {
-                                       if (c.Width.IsRelativeToParent)
-                                               c.RegisterForLayouting (LayoutingType.Width);
-                                       else
-                                               c.RegisterForLayouting (LayoutingType.X);
-                               }
-                               break;
-                       case LayoutingType.Height:
-                               foreach (Widget c in Children) {
-                                       if (c.Height.IsRelativeToParent)
-                                               c.RegisterForLayouting (LayoutingType.Height);
-                                       else
-                                               c.RegisterForLayouting (LayoutingType.Y);
-                               }
-                               break;
-                       }
-                       childrenRWLock.ExitReadLock ();
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       gr.Save ();
-
-                       if (ClipToClientRect) {
-                               //clip to client zone
-                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
-                               gr.Clip ();
-                       }
-
-                       childrenRWLock.EnterReadLock ();
-
-                       for (int i = 0; i < Children.Count; i++) 
-                               Children[i].Paint (ref gr);                     
-
-                       childrenRWLock.ExitReadLock ();
-                       gr.Restore ();
-               }
-               protected override void UpdateCache (Context ctx)
-               {
-                       Rectangle rb = Slot + Parent.ClientRectangle.Position;
-
-
-                       Context gr = new Context (bmp);
-
-                       if (!Clipping.IsEmpty) {
-                               for (int i = 0; i < Clipping.NumRectangles; i++)
-                                       gr.Rectangle(Clipping.GetRectangle(i));
-                               gr.ClipPreserve();
-                               gr.Operator = Operator.Clear;
-                               gr.Fill();
-                               gr.Operator = Operator.Over;
-
-                               base.onDraw (gr);
-
-                               if (ClipToClientRect) {
-                                       CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
-                                       gr.Clip ();
-                               }
-
-                               childrenRWLock.EnterReadLock ();
-
-                               foreach (Widget c in Children) {
-                                       if (!c.Visible)
-                                               continue;
-                                       if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out)
-                                               continue;
-                                       c.Paint (ref gr);
-                               }
-
-                               childrenRWLock.ExitReadLock ();
-
-                               #if DEBUG_CLIP_RECTANGLE
-                               /*gr.LineWidth = 1;
-                               gr.SetSourceColor(Color.DarkMagenta.AdjustAlpha (0.8));
-                               for (int i = 0; i < Clipping.NumRectangles; i++)
-                                       gr.Rectangle(Clipping.GetRectangle(i));
-                               gr.Stroke ();*/
-                               #endif
-                       }
-                       gr.Dispose ();
-
-                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
-                       ctx.Paint ();
-
-                       Clipping.Dispose();
-                       Clipping = new Region ();
-               }
-               #endregion
-
-               public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
-               {
-                       Widget g = sender as Widget;
-
-                       switch (arg.LayoutType) {
-                       case LayoutingType.Width:
-                               if (Width != Measure.Fit)
-                                       return;
-                               if (g.Slot.Width > contentSize.Width) {
-                                       largestChild = g;
-                                       contentSize.Width = g.Slot.Width;
-                               } else if (g == largestChild)
-                                       searchLargestChild ();
-
-                               this.RegisterForLayouting (LayoutingType.Width);
-                               break;
-                       case LayoutingType.Height:
-                               if (Height != Measure.Fit)
-                                       return;
-                               if (g.Slot.Height > contentSize.Height) {
-                                       tallestChild = g;
-                                       contentSize.Height = g.Slot.Height;
-                               } else if (g == tallestChild)
-                                       searchTallestChild ();
-
-                               this.RegisterForLayouting (LayoutingType.Height);
-                               break;
-                       }
-               }
-               //TODO: x,y position should be taken in account for computation of width and height
-               void resetChildrenMaxSize(){
-                       largestChild = null;
-                       tallestChild = null;
-                       contentSize = 0;
-               }
-               void searchLargestChild(){
-                       #if DEBUG_LAYOUTING
-                       Debug.WriteLine("\tSearch largest child");
-                       #endif
-                       largestChild = null;
-                       contentSize.Width = 0;
-                       for (int i = 0; i < Children.Count; i++) {
-                               if (!Children [i].Visible)
-                                       continue;
-                               if (children [i].RegisteredLayoutings.HasFlag (LayoutingType.Width))
-                                       continue;
-                               if (Children [i].Slot.Width > contentSize.Width) {
-                                       contentSize.Width = Children [i].Slot.Width;
-                                       largestChild = Children [i];
-                               }
-                       }
-               }
-               void searchTallestChild(){
-                       #if DEBUG_LAYOUTING
-                       Debug.WriteLine("\tSearch tallest child");
-                       #endif
-                       tallestChild = null;
-                       contentSize.Height = 0;
-                       for (int i = 0; i < Children.Count; i++) {
-                               if (!Children [i].Visible)
-                                       continue;
-                               if (children [i].RegisteredLayoutings.HasFlag (LayoutingType.Height))
-                                       continue;
-                               if (Children [i].Slot.Height > contentSize.Height) {
-                                       contentSize.Height = Children [i].Slot.Height;
-                                       tallestChild = Children [i];
-                               }
-                       }
-               }
-
-
-               #region Mouse handling
-               public override void checkHoverWidget (MouseMoveEventArgs e)
-               {
-                       if (IFace.HoverWidget != this) {
-                               IFace.HoverWidget = this;
-                               onMouseEnter (this, e);
-                       }
-                       for (int i = Children.Count - 1; i >= 0; i--) {
-                               if (Children[i].MouseIsIn(e.Position))
-                               {
-                                       Children[i].checkHoverWidget (e);
-                                       return;
-                               }
-                       }
-                       base.checkHoverWidget (e);
-               }
-//             public override bool PointIsIn (ref Point m)
-//             {
-//                     if (!base.PointIsIn (ref m))
-//                             return false;
-//                     if (CurrentInterface.HoverWidget == this)
-//                             return true;
-//                     lock (Children) {
-//                             for (int i = Children.Count - 1; i >= 0; i--) {
-//                                     if (Children [i].Slot.ContainsOrIsEqual (m) && !(bool)CurrentInterface.HoverWidget?.IsOrIsInside(Children[i])) {                                                
-//                                             return false;
-//                                     }
-//                             }
-//                     }
-//                     return true;
-//             }
-               #endregion
-
-               protected override void Dispose (bool disposing)
-               {
-                       if (disposing) {
-                               foreach (Widget c in children)
-                                       c.Dispose ();
-                       }
-                       base.Dispose (disposing);
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/GroupBox.cs b/Crow/src/GraphicObjects/GroupBox.cs
deleted file mode 100644 (file)
index 2e32ddd..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// GroupBox.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated container accepting one child
-       /// </summary>
-    public class GroupBox : TemplatedContainer
-    {          
-               #region CTOR
-               protected GroupBox () : base(){}
-               public GroupBox(Interface iface) : base(iface){}
-               #endregion
-       }
-}
diff --git a/Crow/src/GraphicObjects/HorizontalStack.cs b/Crow/src/GraphicObjects/HorizontalStack.cs
deleted file mode 100644 (file)
index 64d7cae..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// HorizontalStack.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.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml.Serialization;
-
-namespace Crow
-{
-       /// <summary>
-       /// group control stacking its children horizontally
-       /// </summary>
-    public class HorizontalStack : GenericStack
-    {
-               #region CTOR
-               protected HorizontalStack () : base(){}
-               public HorizontalStack(Interface iface) : base(iface)
-        {            
-        }
-               #endregion
-
-        [XmlIgnore]
-        public override Orientation Orientation
-        {
-            get { return Orientation.Horizontal; }
-        }
-    }
-}
diff --git a/Crow/src/GraphicObjects/HueSelector.cs b/Crow/src/GraphicObjects/HueSelector.cs
deleted file mode 100644 (file)
index eb00a04..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-//
-// HueSelector.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.Xml.Serialization;
-using System.ComponentModel;
-using Crow.Cairo;
-
-namespace Crow
-{
-       [DesignIgnore]
-       public class HueSelector : ColorSelector
-       {
-               #region CTOR
-               protected HueSelector () : base(){}
-               public HueSelector (Interface iface) : base(iface)
-               {
-               }
-               #endregion
-
-               Orientation _orientation;
-               double hue;
-               CursorType cursor = CursorType.Pentagone;
-
-               [DefaultValue(Orientation.Horizontal)]
-               public virtual Orientation Orientation
-               {
-                       get { return _orientation; }
-                       set {
-                               if (_orientation == value)
-                                       return;
-                               _orientation = value;
-                               NotifyValueChanged ("Orientation", _orientation);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               
-               public virtual double Hue {
-                       get { return hue; }
-                       set {
-                               if (hue == value)
-                                       return;
-                               hue = value;
-                               notifyHueChanged ();
-                               updateMousePosFromHue ();
-                               RegisterForRedraw ();
-                       }
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       RectangleD r = ClientRectangle;
-                       r.Height -= 4;
-                       r.Y += 2;
-
-                       Gradient.Type gt = Gradient.Type.Horizontal;
-                       if (Orientation == Orientation.Vertical)
-                               gt = Gradient.Type.Vertical;
-
-                       Gradient grad = new Gradient (gt);
-
-                       grad.Stops.Add (new Gradient.ColorStop (0,     new Color (1, 0, 0, 1)));
-                       grad.Stops.Add (new Gradient.ColorStop (0.167, new Color (1, 1, 0, 1)));
-                       grad.Stops.Add (new Gradient.ColorStop (0.333, new Color (0, 1, 0, 1)));
-                       grad.Stops.Add (new Gradient.ColorStop (0.5,   new Color (0, 1, 1, 1)));
-                       grad.Stops.Add (new Gradient.ColorStop (0.667, new Color (0, 0, 1, 1)));
-                       grad.Stops.Add (new Gradient.ColorStop (0.833, new Color (1, 0, 1, 1)));
-                       grad.Stops.Add (new Gradient.ColorStop (1,     new Color (1, 0, 0, 1)));
-
-                       grad.SetAsSource (gr, r);
-                       CairoHelpers.CairoRectangle (gr, r, CornerRadius);
-                       gr.Fill();
-
-                       r = ClientRectangle;
-
-                       switch (cursor) {
-                       case CursorType.Rectangle:
-                               if (Orientation == Orientation.Horizontal) {
-                                       r.Width = 5;
-                                       r.X = mousePos.X - 2.5;
-                               } else {
-                                       r.Height = 5;
-                                       r.Y = mousePos.Y - 2.5;
-                               }
-                               CairoHelpers.CairoRectangle (gr, r, 1);
-                               break;
-                       case CursorType.Circle:
-                               if (Orientation == Orientation.Horizontal)
-                                       gr.Arc (mousePos.X, r.Center.Y, 3.5, 0, Math.PI * 2.0);
-                               else
-                                       gr.Arc (r.Center.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
-                               break;
-                       case CursorType.Pentagone:
-                               if (Orientation == Orientation.Horizontal) {
-                                       r.Width = 5;
-                                       r.X = mousePos.X - 2.5;
-                                       double y = r.CenterD.Y-r.Height*0.2;
-                                       gr.MoveTo (mousePos.X, y);
-                                       y += r.Height * 0.15;
-                                       gr.LineTo (r.Right, y);
-                                       gr.LineTo (r.Right, r.Bottom-0.5);
-                                       gr.LineTo (r.Left, r.Bottom-0.5);
-                                       gr.LineTo (r.Left, y);
-                                       gr.ClosePath ();
-                               } else { 
-                               }
-                               break;                  
-                       }
-
-                       gr.SetSourceColor (Color.Black);
-                       gr.LineWidth = 2.0;
-                       gr.StrokePreserve ();
-                       gr.SetSourceColor (Color.White);
-                       gr.LineWidth = 1.0;
-                       gr.Stroke ();
-               }
-
-               public override void OnLayoutChanges (LayoutingType layoutType)
-               {
-                       base.OnLayoutChanges (layoutType);
-
-                       if (Orientation == Orientation.Horizontal) {
-                               if (layoutType == LayoutingType.Width)
-                                       updateMousePosFromHue ();
-                       } else if (layoutType == LayoutingType.Height)
-                               updateMousePosFromHue ();
-               }
-               protected override void updateMouseLocalPos (Point mPos)
-               {
-                       base.updateMouseLocalPos (mPos);
-                       if (Orientation == Orientation.Horizontal)
-                               hue = (double)mousePos.X / (double)ClientRectangle.Width;
-                       else
-                               hue = (double)mousePos.Y / (double)ClientRectangle.Height;
-                       notifyHueChanged ();
-                       RegisterForRedraw ();
-               }
-               void updateMousePosFromHue(){
-                       if (Orientation == Orientation.Horizontal)
-                               mousePos.X = (int)Math.Floor(hue * (double)ClientRectangle.Width);
-                       else
-                               mousePos.Y = (int)Math.Floor(hue * (double)ClientRectangle.Height);
-               }
-               void notifyHueChanged(){
-                       NotifyValueChanged ("Hue", hue);
-                       NotifyValueChanged ("HueColor", new SolidColor (Color.FromHSV (hue)));
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/ILayoutable.cs b/Crow/src/GraphicObjects/ILayoutable.cs
deleted file mode 100644 (file)
index c8aa38f..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// ILayoutable.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.Collections.Generic;
-
-namespace Crow
-{
-       public interface ILayoutable
-       {
-               /// <summary> Parent in the graphic tree </summary>
-               ILayoutable Parent { get; set; }
-               /// <summary> The logical parent (used mainly for bindings) as opposed
-               ///  to the parent in the graphic tree </summary>
-               ILayoutable LogicalParent { get; set; }
-
-               Rectangle ClientRectangle { get; }
-               Rectangle getSlot();
-
-               bool ArrangeChildren { get; }
-               LayoutingType RegisteredLayoutings { get; set; }
-               void RegisterForLayouting(LayoutingType layoutType);
-               void RegisterClip(Rectangle clip);
-               bool UpdateLayout(LayoutingType layoutType);
-               bool PointIsIn(ref Point m);
-
-               Rectangle ContextCoordinates(Rectangle r);
-               Rectangle ScreenCoordinates (Rectangle r);
-
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/IMLContainer.cs b/Crow/src/GraphicObjects/IMLContainer.cs
deleted file mode 100644 (file)
index 8ba161a..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// IMLContainer.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;
-
-namespace Crow
-{
-       public class IMLContainer : PrivateContainer
-       {
-               public IMLContainer () : base()
-               {
-               }
-
-               string path;
-
-               public string Path {
-                       get { return path; }
-                       set {
-                               if (path == value)
-                                       return;
-                               path = value;
-                               this.SetChild (IFace.CreateInstance (path));
-                               NotifyValueChanged ("Path", path);
-                       }
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/IValueChange.cs b/Crow/src/GraphicObjects/IValueChange.cs
deleted file mode 100644 (file)
index 7e18e5e..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// IValueChange.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;
-
-namespace Crow
-{
-       public interface IValueChange
-       {
-               event EventHandler<ValueChangeEventArgs> ValueChanged;
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Image.cs b/Crow/src/GraphicObjects/Image.cs
deleted file mode 100644 (file)
index 98f86e5..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-//
-// Image.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 Crow.Cairo;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using System.Diagnostics;
-
-
-namespace Crow
-{
-       /// <summary>
-       /// Base widget to display an image. Accepts bitmaps and SVGs.
-       /// </summary>
-       /// <remarks>
-       /// </remarks>
-       public class Image : Widget
-       {
-               Picture _pic;
-               string _svgSub;
-               bool scaled, keepProps;
-               double opacity;
-
-               #region Public properties
-               /// <summary>
-               /// If false, original size will be kept in any case.
-               /// </summary>
-               [DefaultValue(true)]
-               public virtual bool Scaled {
-                       get { return scaled; }
-                       set {
-                               if (scaled == value)
-                                       return;
-                               scaled = value;
-                               NotifyValueChanged ("Scaled", scaled);
-                               if (_pic == null)
-                                       return;
-                               _pic.Scaled = scaled;
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary>
-               /// If image is scaled, proportions will be preserved.
-               /// </summary>
-               [DefaultValue(true)]
-               public virtual bool KeepProportions {
-                       get { return keepProps; }
-                       set {
-                               if (keepProps == value)
-                                       return;
-                               keepProps = value;
-                               NotifyValueChanged ("KeepProportions", keepProps);
-                               if (_pic == null)
-                                       return;
-                               _pic.KeepProportions = keepProps;
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary>
-               /// Image file path, may be on disk or embedded. Accepts bitmaps or SVG drawings.
-               /// </summary>
-        
-               public string Path {
-                       get { return _pic == null ? "" : _pic.Path; }
-                       set {
-                               if (value == Path)
-                                       return;
-                               try {
-                                       if (string.IsNullOrEmpty(value))
-                                               Picture = null;
-                                       else {
-                                               //lock(IFace.LayoutMutex){
-                                                       LoadImage (value);
-                                               //}
-                                       }
-                               } catch (Exception ex) {
-                                       Debug.WriteLine (ex.Message);
-                                       _pic = null;
-                               }
-                               NotifyValueChanged ("Path", Path);
-                       }
-               }
-               /// <summary>
-               /// Used only for svg images, repaint only node named referenced in SvgSub.
-               /// If null, all the svg is rendered
-               /// </summary>
-               
-               public string SvgSub {
-                       get { return _svgSub; }
-                       set {
-                               if (_svgSub == value)
-                                       return;
-                               _svgSub = value;
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary>
-               /// Object holding the image data once loaded, may be used directely to pupulate this control without 
-               /// specifying a path.
-               /// </summary>
-               
-               public Picture Picture {
-                       get { return _pic; }
-                       set {
-                               if (_pic == value)
-                                       return;
-                               _pic = value;
-                               NotifyValueChanged ("Picture", _pic);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary>
-               /// Opacity parameter for the image
-               /// </summary>
-               // TODO:could be moved in GraphicObject
-               [DefaultValue(1.0)]
-               public virtual double Opacity {
-                       get { return opacity; }
-                       set {
-                               if (opacity == value)
-                                       return;
-                               opacity = value;
-                               NotifyValueChanged ("Faded", opacity);
-                               RegisterForRedraw ();
-                       }
-               }
-               #endregion
-
-               #region CTOR
-               /// <summary>
-               /// Initializes a new instance of the <see cref="Crow.Image"/> class.
-               /// </summary>
-               protected Image () : base(){}
-               /// <summary>
-               /// Initializes a new instance of the <see cref="Crow.Image"/> class from code
-               /// </summary>
-               /// <param name="iface">interface to bound to</param>
-               public Image (Interface iface) : base(iface)
-               {
-               }
-               #endregion
-
-               #region Image Loading
-               public void LoadImage (string path)
-               {
-                       Picture pic;
-                       if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture))
-                               pic = new SvgPicture (path);
-                       else
-                               pic = new BmpPicture (path);
-
-
-                       pic.Scaled = scaled;
-                       pic.KeepProportions = keepProps;
-
-                       Picture = pic;
-               }
-               #endregion
-
-               #region GraphicObject overrides
-               protected override int measureRawSize (LayoutingType lt)
-               {
-                       if (_pic == null)
-                               return 2 * Margin;
-                               //_pic = "#Crow.Images.Icons.IconAlerte.svg";
-                       //TODO:take scalling in account
-                       if (lt == LayoutingType.Width)
-                               return _pic.Dimensions.Width + 2 * Margin;
-                       else
-                               return _pic.Dimensions.Height + 2 * Margin;
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       if (_pic == null)
-                               return;
-
-                       _pic.Paint (gr, ClientRectangle, _svgSub);
-
-                       if (Opacity<1.0) {
-                               gr.SetSourceRGBA (0.0, 0.0, 0.0, 1.0-Opacity);
-                               gr.Operator = Operator.DestOut;
-                               gr.Rectangle (ClientRectangle);
-                               gr.Fill ();
-                               gr.Operator = Operator.Over;
-                       }
-               }
-               #endregion
-       }
-}
diff --git a/Crow/src/GraphicObjects/Label.cs b/Crow/src/GraphicObjects/Label.cs
deleted file mode 100644 (file)
index f597f5d..0000000
+++ /dev/null
@@ -1,833 +0,0 @@
-//
-// Label.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.Collections.Generic;
-using System.Linq;
-using System.Diagnostics;
-using Crow.Cairo;
-using System.Text.RegularExpressions;
-using System.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-    public class Label : Widget
-    {
-               #region CTOR
-               protected Label () : base(){}
-
-               public Label(Interface iface) : base(iface)
-               {
-
-               }
-//             public Label(string _text)
-//                     : base()
-//             {
-//                     Text = _text;
-//             }
-               #endregion
-
-               public event EventHandler<TextChangeEventArgs> TextChanged;
-
-               public virtual void OnTextChanged(Object sender, TextChangeEventArgs e)
-               {
-                       textMeasureIsUpToDate = false;
-                       NotifyValueChanged ("Text", Text);
-                       TextChanged.Raise (this, e);
-               }
-        //TODO:change protected to private
-
-               #region private and protected fields
-               string _text = "label";
-        Alignment _textAlignment;
-               bool horizontalStretch;
-               bool verticalStretch;
-               bool _selectable;
-               bool _multiline;
-               Color selBackground;
-               Color selForeground;
-               Point mouseLocalPos = -1;//mouse coord in widget space, filled only when clicked
-               int _currentCol;        //0 based cursor position in string
-               int _currentLine;
-               Point _selBegin = -1;   //selection start (row,column)
-               Point _selRelease = -1; //selection end (row,column)
-               double textCursorPos;   //cursor position in cairo units in widget client coord.
-               double SelStartCursorPos = -1;
-               double SelEndCursorPos = -1;
-               bool SelectionInProgress = false;
-
-        protected Rectangle rText;
-               protected float widthRatio = 1f;
-               protected float heightRatio = 1f;
-               protected FontExtents fe;
-               protected TextExtents te;
-               #endregion
-
-               [DefaultValue("SteelBlue")]
-               public virtual Color SelectionBackground {
-                       get { return selBackground; }
-                       set {
-                               if (value == selBackground)
-                                       return;
-                               selBackground = value;
-                               NotifyValueChanged ("SelectionBackground", selBackground);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue("White")]
-               public virtual Color SelectionForeground {
-                       get { return selForeground; }
-                       set {
-                               if (value == selForeground)
-                                       return;
-                               selForeground = value;
-                               NotifyValueChanged ("SelectionForeground", selForeground);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(Alignment.Left)]
-               public Alignment TextAlignment
-        {
-            get { return _textAlignment; }
-            set {
-                               if (value == _textAlignment)
-                                       return;
-                               _textAlignment = value;
-                               RegisterForRedraw ();
-                               NotifyValueChanged ("TextAlignment", _textAlignment);
-                       }
-        }
-               [DefaultValue(false)]
-               public virtual bool HorizontalStretch {
-                       get { return horizontalStretch; }
-                       set {
-                               if (horizontalStretch == value)
-                                       return;
-                               horizontalStretch = value;
-                               RegisterForRedraw ();
-                               NotifyValueChanged ("HorizontalStretch", horizontalStretch);
-                       }
-               }
-               [DefaultValue(false)]
-               public virtual bool VerticalStretch {
-                       get { return verticalStretch; }
-                       set {
-                               if (verticalStretch == value)
-                                       return;
-                               verticalStretch = value;
-                               RegisterForRedraw ();
-                               NotifyValueChanged ("VerticalStretch", verticalStretch);
-                       }
-               }
-               [DefaultValue("label")]
-        public string Text
-        {
-            get {
-                               return lines == null ?
-                                       _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j);
-                       }
-            set
-            {
-                               if (string.Equals (value, _text, StringComparison.Ordinal))
-                    return;
-
-                _text = value;
-
-                               if (string.IsNullOrEmpty(_text))
-                                       _text = "";
-
-                               lines = getLines;
-
-                               OnTextChanged (this, new TextChangeEventArgs (Text));
-                               RegisterForGraphicUpdate ();
-            }
-        }
-               [DefaultValue(false)]
-               public bool Selectable
-               {
-                       get { return _selectable; }
-                       set
-                       {
-                               if (value == _selectable)
-                                       return;
-                               _selectable = value;
-                               NotifyValueChanged ("Selectable", _selectable);
-                               SelBegin = -1;
-                               SelRelease = -1;
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(false)]
-               public bool Multiline
-               {
-                       get { return _multiline; }
-                       set
-                       {
-                               if (value == _multiline)
-                                       return;
-                               _multiline = value;
-                               NotifyValueChanged ("Multiline", _multiline);
-                               RegisterForGraphicUpdate();
-                       }
-               }
-               [DefaultValue(0)]
-               public int CurrentColumn{
-                       get { return _currentCol; }
-                       set {
-                               if (value == _currentCol)
-                                       return;
-                               if (value < 0)
-                                       _currentCol = 0;
-                               else if (value > lines [_currentLine].Length)
-                                       _currentCol = lines [_currentLine].Length;
-                               else
-                                       _currentCol = value;
-                               NotifyValueChanged ("CurrentColumn", _currentCol);
-                       }
-               }
-               [DefaultValue(0)]
-               public int CurrentLine{
-                       get { return _currentLine; }
-                       set {
-                               if (value == _currentLine)
-                                       return;
-                               if (value >= lines.Count)
-                                       _currentLine = lines.Count-1;
-                               else if (value < 0)
-                                       _currentLine = 0;
-                               else
-                                       _currentLine = value;
-                               //force recheck of currentCol for bounding
-                               int cc = _currentCol;
-                               _currentCol = 0;
-                               CurrentColumn = cc;
-                               NotifyValueChanged ("CurrentLine", _currentLine);
-                       }
-               }
-               [XmlIgnore]public Point CurrentPosition {
-                       get { return new Point(_currentCol, CurrentLine); }
-               }
-               //TODO:using HasFocus for drawing selection cause SelBegin and Release binding not to work
-               /// <summary>
-               /// Selection begin position in char units
-               /// </summary>
-               [DefaultValue("-1")]
-               public Point SelBegin {
-                       get {
-                               return _selBegin;
-                       }
-                       set {
-                               if (value == _selBegin)
-                                       return;
-                               _selBegin = value;
-                               NotifyValueChanged ("SelBegin", _selBegin);
-                               NotifyValueChanged ("SelectedText", SelectedText);
-                       }
-               }
-               [DefaultValue("-1")]
-               public Point SelRelease {
-                       get {
-                               return _selRelease;
-                       }
-                       set {
-                               if (value == _selRelease)
-                                       return;
-                               _selRelease = value;
-                               NotifyValueChanged ("SelRelease", _selRelease);
-                               NotifyValueChanged ("SelectedText", SelectedText);
-                       }
-               }
-               /// <summary>
-               /// return char at CurrentLine, CurrentColumn
-               /// </summary>
-               [XmlIgnore]protected Char CurrentChar
-               {
-                       get {
-                               return lines [CurrentLine] [CurrentColumn];
-                       }
-               }
-               /// <summary>
-               /// ordered selection start and end positions in char units
-               /// </summary>
-               [XmlIgnore]protected Point selectionStart
-               {
-                       get {
-                               return SelRelease < 0 || SelBegin.Y < SelRelease.Y ? SelBegin :
-                                       SelBegin.Y > SelRelease.Y ? SelRelease :
-                                       SelBegin.X < SelRelease.X ? SelBegin : SelRelease;
-                       }
-               }
-               [XmlIgnore]public Point selectionEnd
-               {
-                       get {
-                               return SelRelease < 0 || SelBegin.Y > SelRelease.Y ? SelBegin :
-                                       SelBegin.Y < SelRelease.Y ? SelRelease :
-                                       SelBegin.X > SelRelease.X ? SelBegin : SelRelease;
-                       }
-               }
-               [XmlIgnore]public string SelectedText
-               {
-                       get {
-
-                               if (SelRelease < 0 || SelBegin < 0)
-                                       return "";
-                               if (selectionStart.Y == selectionEnd.Y)
-                                       return lines [selectionStart.Y].Substring (selectionStart.X, selectionEnd.X - selectionStart.X);
-                               string tmp = "";
-                               tmp = lines [selectionStart.Y].Substring (selectionStart.X);
-                               for (int l = selectionStart.Y + 1; l < selectionEnd.Y; l++) {
-                                       tmp += Interface.LineBreak + lines [l];
-                               }
-                               tmp += Interface.LineBreak + lines [selectionEnd.Y].Substring (0, selectionEnd.X);
-                               return tmp;
-                       }
-               }
-               [XmlIgnore]public bool selectionIsEmpty
-               { get { return SelRelease < 0; } }
-
-               List<string> lines;
-               List<string> getLines {
-                       get {
-                               return _multiline ?
-                                       Regex.Split (_text, "\r\n|\r|\n|\\\\n").ToList() :
-                                       new List<string>(new string[] { _text });
-                       }
-               }
-               /// <summary>
-               /// Moves cursor one char to the left.
-               /// </summary>
-               /// <returns><c>true</c> if move succeed</returns>
-               public bool MoveLeft(){
-                       int tmp = _currentCol - 1;
-                       if (tmp < 0) {
-                               if (_currentLine == 0)
-                                       return false;
-                               CurrentLine--;
-                               CurrentColumn = int.MaxValue;
-                       } else
-                               CurrentColumn = tmp;
-                       return true;
-               }
-               /// <summary>
-               /// Moves cursor one char to the right.
-               /// </summary>
-               /// <returns><c>true</c> if move succeed</returns>
-               public bool MoveRight(){
-                       int tmp = _currentCol + 1;
-                       if (tmp > lines [_currentLine].Length){
-                               if (CurrentLine == lines.Count - 1)
-                                       return false;
-                               CurrentLine++;
-                               CurrentColumn = 0;
-                       } else
-                               CurrentColumn = tmp;
-                       return true;
-               }
-               public void GotoWordStart(){
-                       CurrentColumn--;
-                       //skip white spaces
-                       while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0)
-                               CurrentColumn--;
-                       while (char.IsLetterOrDigit (lines [CurrentLine] [CurrentColumn]) && CurrentColumn > 0)
-                               CurrentColumn--;
-                       if (!char.IsLetterOrDigit (this.CurrentChar))
-                               CurrentColumn++;
-               }
-               public void GotoWordEnd(){
-                       //skip white spaces
-                       if (CurrentColumn >= lines [CurrentLine].Length - 1)
-                               return;
-                       while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < lines [CurrentLine].Length-1)
-                               CurrentColumn++;
-                       while (char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < lines [CurrentLine].Length-1)
-                               CurrentColumn++;
-                       if (char.IsLetterOrDigit (this.CurrentChar))
-                               CurrentColumn++;
-               }
-               public void DeleteChar()
-               {
-                       if (selectionIsEmpty) {
-                               if (CurrentColumn == 0) {
-                                       if (CurrentLine == 0 && lines.Count == 1)
-                                               return;
-                                       CurrentLine--;
-                                       CurrentColumn = lines [CurrentLine].Length;
-                                       lines [CurrentLine] += lines [CurrentLine + 1];
-                                       lines.RemoveAt (CurrentLine + 1);
-
-                                       OnTextChanged (this, new TextChangeEventArgs (Text));
-                                       return;
-                               }
-                               CurrentColumn--;
-                               lines [CurrentLine] = lines [CurrentLine].Remove (CurrentColumn, 1);
-                       } else {
-                               int linesToRemove = selectionEnd.Y - selectionStart.Y + 1;
-                               int l = selectionStart.Y;
-
-                               if (linesToRemove > 0) {
-                                       lines [l] = lines [l].Remove (selectionStart.X, lines [l].Length - selectionStart.X) +
-                                               lines [selectionEnd.Y].Substring (selectionEnd.X, lines [selectionEnd.Y].Length - selectionEnd.X);
-                                       l++;
-                                       for (int c = 0; c < linesToRemove-1; c++)
-                                               lines.RemoveAt (l);
-                                       CurrentLine = selectionStart.Y;
-                                       CurrentColumn = selectionStart.X;
-                               } else
-                                       lines [l] = lines [l].Remove (selectionStart.X, selectionEnd.X - selectionStart.X);
-                               CurrentColumn = selectionStart.X;
-                               SelBegin = -1;
-                               SelRelease = -1;
-                       }
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
-               }
-               /// <summary>
-               /// Insert new string at caret position, should be sure no line break is inside.
-               /// </summary>
-               /// <param name="str">String.</param>
-               protected void Insert(string str)
-               {
-                       if (!selectionIsEmpty)
-                               this.DeleteChar ();
-                       if (_multiline) {
-                               string[] strLines = Regex.Split (str, "\r\n|\r|\n|" + @"\\n").ToArray();
-                               lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, strLines[0]);
-                               CurrentColumn += strLines[0].Length;
-                               for (int i = 1; i < strLines.Length; i++) {
-                                       InsertLineBreak ();
-                                       lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, strLines[i]);
-                                       CurrentColumn += strLines[i].Length;
-                               }
-                       } else {
-                               lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, str);
-                               CurrentColumn += str.Length;
-                       }
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
-               }
-               /// <summary>
-               /// Insert a line break.
-               /// </summary>
-               protected void InsertLineBreak()
-               {
-                       lines.Insert(CurrentLine + 1, lines[CurrentLine].Substring(CurrentColumn));
-                       lines [CurrentLine] = lines [CurrentLine].Substring (0, CurrentColumn);
-                       CurrentLine++;
-                       CurrentColumn = 0;
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
-               }
-               bool textMeasureIsUpToDate = false;
-               Size cachedTextSize = default(Size);
-
-               #region GraphicObject overrides
-               protected override int measureRawSize(LayoutingType lt)
-               {
-                       if (lines == null)
-                               lines = getLines;
-                       if (!textMeasureIsUpToDate) {
-                               using (Context gr = new Context (IFace.surf)) {
-                                       //Cairo.FontFace cf = gr.GetContextFontFace ();
-
-                                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
-                                       gr.SetFontSize (Font.Size);
-                                       gr.FontOptions = Interface.FontRenderingOptions;
-                                       gr.Antialias = Interface.Antialias;
-
-                                       fe = gr.FontExtents;
-                                       te = new TextExtents ();
-
-                                       cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent+fe.Descent) * Math.Max (1, lines.Count)) + Margin * 2;
-
-                                       try {
-                                               for (int i = 0; i < lines.Count; i++) {
-                                                       string l = lines[i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
-
-                                                       TextExtents tmp = gr.TextExtents (l);
-
-                                                       if (tmp.XAdvance > te.XAdvance)
-                                                               te = tmp;
-                                               }
-                                               cachedTextSize.Width = (int)Math.Ceiling (te.XAdvance) + Margin * 2;
-                                               textMeasureIsUpToDate = true;
-                                       } catch {                                                       
-                                               return -1;
-                                       }                                       
-                               }
-                       }
-                       return lt == LayoutingType.Height ? cachedTextSize.Height : cachedTextSize.Width;
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
-                       gr.SetFontSize (Font.Size);
-                       gr.FontOptions = Interface.FontRenderingOptions;
-                       gr.Antialias = Interface.Antialias;
-
-                       rText = new Rectangle(new Size(
-                               measureRawSize(LayoutingType.Width), measureRawSize(LayoutingType.Height)));
-                       rText.Width -= 2 * Margin;
-                       rText.Height -= 2 * Margin;
-
-                       widthRatio = 1f;
-                       heightRatio = 1f;
-
-                       Rectangle cb = ClientRectangle;
-
-                       rText.X = cb.X;
-                       rText.Y = cb.Y;
-
-                       if (horizontalStretch) {
-                               widthRatio = (float)cb.Width / (float)rText.Width;
-                               if (!verticalStretch)
-                                       heightRatio = widthRatio;
-                       }
-
-                       if (verticalStretch) {
-                               heightRatio = (float)cb.Height / (float)rText.Height;
-                               if (!horizontalStretch)
-                                       widthRatio = heightRatio;
-                       }
-
-                       rText.Width = (int)(widthRatio * (float)rText.Width);
-                       rText.Height = (int)(heightRatio * (float)rText.Height);
-
-                       switch (TextAlignment)
-                       {
-                       case Alignment.TopLeft:     //ok
-                               rText.X = cb.X;
-                               rText.Y = cb.Y;
-                               break;
-                       case Alignment.Top:   //ok
-                               rText.Y = cb.Y;
-                               rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
-                               break;
-                       case Alignment.TopRight:    //ok
-                               rText.Y = cb.Y;
-                               rText.X = cb.Right - rText.Width;
-                               break;
-                       case Alignment.Left://ok
-                               rText.X = cb.X;
-                               rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
-                               break;
-                       case Alignment.Right://ok
-                               rText.X = cb.X + cb.Width - rText.Width;
-                               rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
-                               break;
-                       case Alignment.Bottom://ok
-                               rText.X = cb.Width / 2 - rText.Width / 2;
-                               rText.Y = cb.Height - rText.Height;
-                               break;
-                       case Alignment.BottomLeft://ok
-                               rText.X = cb.X;
-                               rText.Y = cb.Bottom - rText.Height;
-                               break;
-                       case Alignment.BottomRight://ok
-                               rText.Y = cb.Bottom - rText.Height;
-                               rText.X = cb.Right - rText.Width;
-                               break;
-                       case Alignment.Center://ok
-                               rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
-                               //rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
-                               rText.Y = cb.Y + (int)Math.Floor((double)cb.Height / 2.0 - (double)rText.Height / 2.0);
-                               break;
-                       }
-
-                       //gr.FontMatrix = new Matrix(widthRatio * (float)Font.Size, 0, 0, heightRatio * (float)Font.Size, 0, 0);
-                       fe = gr.FontExtents;
-
-                       #region draw text cursor
-                       if (HasFocus && Selectable)
-                       {
-                               if (mouseLocalPos >= 0)
-                               {
-                                       computeTextCursor(gr);
-
-                                       if (SelectionInProgress)
-                                       {
-                                               if (SelBegin < 0){
-                                                       SelBegin = new Point(CurrentColumn, CurrentLine);
-                                                       SelStartCursorPos = textCursorPos;
-                                                       SelRelease = -1;
-                                               }else{
-                                                       SelRelease = new Point(CurrentColumn, CurrentLine);
-                                                       if (SelRelease == SelBegin)
-                                                               SelRelease = -1;
-                                                       else
-                                                               SelEndCursorPos = textCursorPos;
-                                               }
-                                       }else
-                                               computeTextCursorPosition(gr);
-                               }else
-                                       computeTextCursorPosition(gr);
-
-                               Foreground.SetAsSource (gr);
-                               gr.LineWidth = 1.0;
-                               gr.MoveTo (0.5 + textCursorPos + rText.X, rText.Y + CurrentLine * (fe.Ascent+fe.Descent));
-                               gr.LineTo (0.5 + textCursorPos + rText.X, rText.Y + (CurrentLine + 1) * (fe.Ascent+fe.Descent));
-                               gr.Stroke();
-                       }
-                       #endregion
-
-                       //****** debug selection *************
-//                     if (SelRelease >= 0) {
-//                             new SolidColor(Color.DarkGreen).SetAsSource(gr);
-//                             Rectangle R = new Rectangle (
-//                                                  rText.X + (int)SelEndCursorPos - 3,
-//                                                  rText.Y + (int)(SelRelease.Y * (fe.Ascent+fe.Descent)),
-//                                                  6,
-//                                                  (int)(fe.Ascent+fe.Descent));
-//                             gr.Rectangle (R);
-//                             gr.Fill ();
-//                     }
-//                     if (SelBegin >= 0) {
-//                             new SolidColor(Color.DarkRed).SetAsSource(gr);
-//                             Rectangle R = new Rectangle (
-//                                     rText.X + (int)SelStartCursorPos - 3,
-//                                     rText.Y + (int)(SelBegin.Y * (fe.Ascent+fe.Descent)),
-//                                     6,
-//                                     (int)(fe.Ascent+fe.Descent));
-//                             gr.Rectangle (R);
-//                             gr.Fill ();
-//                     }
-                       //*******************
-
-                       for (int i = 0; i < lines.Count; i++) {
-                               string l = lines [i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
-                               int lineLength = (int)gr.TextExtents (l).XAdvance;
-                               Rectangle lineRect = new Rectangle (
-                                       rText.X,
-                                       rText.Y + i * (int)(fe.Ascent+fe.Descent),
-                                       lineLength,
-                                       (int)(fe.Ascent+fe.Descent));
-
-//                             if (TextAlignment == Alignment.Center ||
-//                                     TextAlignment == Alignment.Top ||
-//                                     TextAlignment == Alignment.Bottom)
-//                                     lineRect.X += (rText.Width - lineLength) / 2;
-//                             else if (TextAlignment == Alignment.Right ||
-//                                     TextAlignment == Alignment.TopRight ||
-//                                     TextAlignment == Alignment.BottomRight)
-//                                     lineRect.X += (rText.Width - lineLength);
-                               if (string.IsNullOrWhiteSpace (l))
-                                       continue;
-
-                               Foreground.SetAsSource (gr);
-                               gr.MoveTo (lineRect.X,(double)rText.Y + fe.Ascent + (fe.Ascent+fe.Descent) * i) ;
-
-                gr.ShowText (l);
-                               gr.Fill ();
-
-                               if (Selectable) {
-                                       if (SelRelease >= 0 && i >= selectionStart.Y && i <= selectionEnd.Y) {
-                                               gr.SetSourceColor (selBackground);
-
-                                               Rectangle selRect = lineRect;
-
-                                               int cpStart = (int)SelStartCursorPos,
-                                               cpEnd = (int)SelEndCursorPos;
-
-                                               if (SelBegin.Y > SelRelease.Y) {
-                                                       cpStart = cpEnd;
-                                                       cpEnd = (int)SelStartCursorPos;
-                                               }
-
-                                               if (i == selectionStart.Y) {
-                                                       selRect.Width -= cpStart;
-                                                       selRect.Left += cpStart;
-                                               }
-                                               if (i == selectionEnd.Y)
-                                                       selRect.Width -= (lineLength - cpEnd);
-
-                                               gr.Rectangle (selRect);
-                                               gr.FillPreserve ();
-                                               gr.Save ();
-                                               gr.Clip ();
-                                               gr.SetSourceColor (SelectionForeground);
-                                               gr.MoveTo (lineRect.X, rText.Y + fe.Ascent + (fe.Ascent+fe.Descent) * i);
-                                               gr.ShowText (l);
-                                               gr.Fill ();
-                                               gr.Restore ();
-                                       }
-                               }
-                       }
-               }
-               #endregion
-
-               #region Mouse handling
-               void updatemouseLocalPos(Point mpos){
-                       mouseLocalPos = mpos - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft;
-                       if (mouseLocalPos.X < 0)
-                               mouseLocalPos.X = 0;
-                       if (mouseLocalPos.Y < 0)
-                               mouseLocalPos.Y = 0;
-               }
-               protected override void onFocused (object sender, EventArgs e)
-               {
-                       base.onFocused (sender, e);
-
-                       if (!_selectable)
-                               return;
-                       SelBegin = new Point(0,0);
-                       SelRelease = new Point (lines.LastOrDefault ().Length, lines.Count-1);
-                       RegisterForRedraw ();
-               }
-               protected override void onUnfocused (object sender, EventArgs e)
-               {
-                       base.onUnfocused (sender, e);
-
-                       SelBegin = -1;
-                       SelRelease = -1;
-                       RegisterForRedraw ();
-               }
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseMove (sender, e);
-
-                       if (!(SelectionInProgress && HasFocus && _selectable))
-                               return;
-
-                       updatemouseLocalPos (e.Position);
-
-                       RegisterForRedraw();
-               }
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       if (this.HasFocus && _selectable){
-                               updatemouseLocalPos (e.Position);
-                               SelBegin = -1;
-                               SelRelease = -1;
-                               SelectionInProgress = true;
-                               RegisterForRedraw();//TODO:should put it in properties
-                       }
-
-                       //done at the end to set 'hasFocus' value after testing it
-                       base.onMouseDown (sender, e);
-               }
-               public override void onMouseUp (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseUp (sender, e);
-                       if (!(this.HasFocus || _selectable))
-                               return;
-                       if (!SelectionInProgress)
-                               return;
-
-                       updatemouseLocalPos (e.Position);
-                       SelectionInProgress = false;
-                       RegisterForRedraw ();
-               }
-               public override void onMouseDoubleClick (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseDoubleClick (sender, e);
-                       if (!(this.HasFocus || _selectable))
-                               return;
-                       
-                       GotoWordStart ();
-                       SelBegin = CurrentPosition;
-                       GotoWordEnd ();
-                       SelRelease = CurrentPosition;
-                       SelectionInProgress = false;
-                       RegisterForRedraw ();
-               }
-               #endregion
-
-               /// <summary>
-               /// Update Current Column, line and TextCursorPos
-               /// from mouseLocalPos
-               /// </summary>
-               void computeTextCursor(Context gr)
-               {
-                       TextExtents te;
-
-                       double cPos = 0f;
-
-                       CurrentLine = (int)(mouseLocalPos.Y / (fe.Ascent+fe.Descent));
-
-                       //fix cu
-                       if (CurrentLine >= lines.Count)
-                               CurrentLine = lines.Count - 1;
-
-                       switch (TextAlignment) {
-                       case Alignment.Center:
-                       case Alignment.Top:
-                       case Alignment.Bottom:
-                               cPos+= ClientRectangle.Width - gr.TextExtents(lines [CurrentLine]).Width/2.0;
-                               break;
-                       case Alignment.Right:
-                       case Alignment.TopRight:
-                       case Alignment.BottomRight:
-                               cPos += ClientRectangle.Width - gr.TextExtents(lines [CurrentLine]).Width;
-                               break;
-                       }
-
-                       for (int i = 0; i < lines[CurrentLine].Length; i++)
-                       {
-                               string c = lines [CurrentLine].Substring (i, 1);
-                               if (c == "\t")
-                                       c = new string (' ', Interface.TAB_SIZE);
-
-                               te = gr.TextExtents(c);
-
-                               double halfWidth = te.XAdvance / 2;
-
-                               if (mouseLocalPos.X <= cPos + halfWidth)
-                               {
-                                       CurrentColumn = i;
-                                       textCursorPos = cPos;
-                                       mouseLocalPos = -1;
-                                       return;
-                               }
-
-                               cPos += te.XAdvance;
-                       }
-                       CurrentColumn = lines[CurrentLine].Length;
-                       textCursorPos = cPos;
-
-                       //reset mouseLocalPos
-                       mouseLocalPos = -1;
-               }
-               /// <summary> Computes offsets in cairo units </summary>
-               void computeTextCursorPosition(Context gr)
-               {
-                       if (SelBegin >= 0)
-                               SelStartCursorPos = GetXFromTextPointer (gr, SelBegin);
-                       if (SelRelease >= 0)
-                               SelEndCursorPos = GetXFromTextPointer (gr, SelRelease);
-                       textCursorPos = GetXFromTextPointer (gr, new Point(CurrentColumn, CurrentLine));
-               }
-               /// <summary> Compute x offset in cairo unit from text position </summary>
-               double GetXFromTextPointer(Context gr, Point pos)
-               {
-                       try {
-                               string l = lines [pos.Y].Substring (0, pos.X).
-                                       Replace ("\t", new String (' ', Interface.TAB_SIZE));
-                               return gr.TextExtents (l).XAdvance;
-                       } catch{
-                               return -1;
-                       }
-               }
-    }
-}
diff --git a/Crow/src/GraphicObjects/ListBox.cs b/Crow/src/GraphicObjects/ListBox.cs
deleted file mode 100644 (file)
index 438e8d6..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// ListBox.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.Collections;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using System.IO;
-using System.Diagnostics;
-using System.Xml;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace Crow
-{
-       public class ListBox : TemplatedGroup
-       {
-               #region CTOR
-               protected ListBox () : base(){}
-               public ListBox (Interface iface) : base(iface) {}
-               #endregion
-
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Menu.cs b/Crow/src/GraphicObjects/Menu.cs
deleted file mode 100644 (file)
index 85f5485..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Menu.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       public class Menu : TemplatedGroup
-       {
-               #region CTOR
-               protected Menu () : base(){}
-               public Menu (Interface iface) : base(iface) {}
-               #endregion
-
-               Orientation orientation;
-               bool autoOpen = false;
-
-               #region Public properties
-               [DefaultValue(Orientation.Horizontal)]
-               public Orientation Orientation {
-                       get { return orientation; }
-                       set {
-                               if (orientation == value)
-                                       return;
-                               orientation = value;
-                               NotifyValueChanged ("Orientation", orientation);
-                       }
-               }
-               [XmlIgnore]public bool AutomaticOpening
-               {
-                       get { return autoOpen; }
-                       set     {
-                               if (autoOpen == value)
-                                       return;
-                               autoOpen = value;
-                               NotifyValueChanged ("AutomaticOpening", autoOpen);
-                       }
-               }
-               #endregion
-
-               public override void AddItem (Widget g)
-               {                       
-                       base.AddItem (g);
-
-                       if (orientation == Orientation.Horizontal)
-                               g.NotifyValueChanged ("PopDirection", Alignment.Bottom);
-                       else
-                               g.NotifyValueChanged ("PopDirection", Alignment.Right);
-               }
-               public override void onMouseLeave (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseLeave (sender, e);
-                       AutomaticOpening = false;
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/MenuItem.cs b/Crow/src/GraphicObjects/MenuItem.cs
deleted file mode 100644 (file)
index abc9d11..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-//
-// MenuItem.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       public class MenuItem : Menu
-       {
-               #region CTOR
-               protected MenuItem () : base(){}
-               public MenuItem (Interface iface) : base(iface) {}
-               #endregion
-
-               public event EventHandler Open;
-               public event EventHandler Close;
-
-               Command command;
-               Picture icon;
-               bool isOpened;
-               Measure popWidth, popHeight;
-
-               #region Public properties
-               [DefaultValue(false)]
-               public bool IsOpened {
-                       get { return isOpened; }
-                       set {
-                               if (isOpened == value)
-                                       return;
-                               isOpened = value;
-                               NotifyValueChanged ("IsOpened", isOpened);
-
-                               if (isOpened) {
-                                       onOpen (this, null);
-                                       if (LogicalParent is Menu)
-                                               (LogicalParent as Menu).AutomaticOpening = true;
-                               }else
-                                       onClose (this, null);
-                       }
-               }
-               [DefaultValue(null)]
-               public virtual Command Command {
-                       get { return command; }
-                       set {
-                               if (command == value)
-                                       return;
-
-                               if (command != null) {
-                                       command.raiseAllValuesChanged ();
-                                       command.ValueChanged -= Command_ValueChanged;
-                               }
-
-                               command = value;
-
-                               if (command != null) {
-                                       command.ValueChanged += Command_ValueChanged;
-                                       command.raiseAllValuesChanged ();
-                               }
-
-                               NotifyValueChanged ("Command", command);
-                       }
-               }
-               
-               public override bool IsEnabled {
-                       get { return Command == null ? base.IsEnabled : Command.CanExecute; }
-                       set { base.IsEnabled = value; }
-               }
-               
-               public override string Caption {
-                       get { return Command == null ? base.Caption : Command.Caption; }
-                       set { base.Caption = value; }
-               }
-               
-               public Picture Icon {
-                       get { return Command == null ? icon : Command.Icon;; }
-                       set {
-                               if (icon == value)
-                                       return;
-                               icon = value;
-                               if (command == null)
-                                       NotifyValueChanged ("Icon", icon);
-                       }
-               }
-               [DefaultValue("Fit")]
-               public virtual Measure PopWidth {
-                       get { return popWidth; }
-                       set {
-                               if (popWidth == value)
-                                       return;
-                               popWidth = value;
-                               NotifyValueChanged ("PopWidth", popWidth);
-                       }
-               }
-               [DefaultValue("Fit")]
-               public virtual Measure PopHeight {
-                       get { return popHeight; }
-                       set {
-                               if (popHeight == value)
-                                       return;
-                               popHeight = value;
-                               NotifyValueChanged ("PopHeight", popHeight);
-                       }
-               }
-               #endregion
-
-               public override void AddItem (Widget g)
-               {
-                       base.AddItem (g);
-                       g.NotifyValueChanged ("PopDirection", Alignment.Right);
-               }
-
-               void Command_ValueChanged (object sender, ValueChangeEventArgs e)
-               {
-                       string mName = e.MemberName;
-                       if (mName == "CanExecute")
-                               mName = "IsEnabled";
-                       NotifyValueChanged (mName, e.NewValue);
-               }
-               protected virtual void onOpen (object sender, EventArgs e){
-                       Open.Raise (this, null);
-               }
-               protected virtual void onClose (object sender, EventArgs e){
-                       System.Diagnostics.Debug.WriteLine ("close: " + this.ToString());
-                       Close.Raise (this, null);
-               }
-               public override bool MouseIsIn (Point m)
-               {
-                       return IsEnabled && !IsDragged ? base.MouseIsIn (m) || child.MouseIsIn (m) : false;
-               }
-               public override void onMouseEnter (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseEnter (sender, e);
-                       Menu menu = LogicalParent as Menu;
-                       if (menu == null)
-                               return;
-                       if (menu.AutomaticOpening && items.Children.Count>0)
-                               IsOpened = true;
-               }
-               public override void onMouseLeave (object sender, MouseMoveEventArgs e)
-               {
-                       if (IsOpened)
-                               IsOpened = false;
-                       base.onMouseLeave (this, e);
-               }
-               public override void onMouseClick (object sender, MouseButtonEventArgs e)
-               {
-#if DEBUG_FOCUS
-                       System.Diagnostics.Debug.WriteLine ("MENU CLICK => " + this.ToString ());
-#endif
-                       if (command != null) {
-                               command.Execute ();
-                               closeMenu ();
-                       }
-                       if (hasClick)
-                               base.onMouseClick (sender, e);
-
-                       if (!IsOpened)
-                               (LogicalParent as Menu).AutomaticOpening = false;
-               }
-               void closeMenu () {
-                       MenuItem tmp = LogicalParent as MenuItem;
-                       while (tmp != null) {
-                               tmp.IsOpened = false;
-                               tmp.Background = Color.Transparent;
-                               tmp.AutomaticOpening = false;
-                               tmp = tmp.LogicalParent as MenuItem;
-                       }
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/MessageBox.cs b/Crow/src/GraphicObjects/MessageBox.cs
deleted file mode 100644 (file)
index e5746c6..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-//
-// MessageBox.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       public class MessageBox : Window
-       {
-               #region CTOR
-               protected MessageBox () : base(){}
-               public MessageBox (Interface iface) : base(iface){}
-               #endregion
-
-               public enum Type {
-                       None,
-                       Information,
-                       Alert,
-                       Error,
-                       YesNo,
-                       YesNoCancel,
-
-               }
-
-               protected override void loadTemplate (Widget template)
-               {
-                       base.loadTemplate (template);
-                       NotifyValueChanged ("MsgIcon", "#Crow.Icons.iconInfo.svg");
-               }
-               string message, okMessage, cancelMessage, noMessage;
-               Type msgType = Type.None;
-
-               public event EventHandler Yes;
-               public event EventHandler No;
-               public event EventHandler Cancel;
-
-               [DefaultValue("Informations")]
-               public virtual string Message
-               {
-                       get { return message; }
-                       set {
-                               if (message == value)
-                                       return;
-                               message = value;
-                               NotifyValueChanged ("Message", message);
-                       }
-               }
-               [DefaultValue("Ok")]
-               public virtual string OkMessage
-               {
-                       get { return okMessage; }
-                       set {
-                               if (okMessage == value)
-                                       return;
-                               okMessage = value;
-                               NotifyValueChanged ("OkMessage", okMessage);
-                       }
-               }
-               [DefaultValue("Cancel")]
-               public virtual string CancelMessage
-               {
-                       get { return cancelMessage; }
-                       set {
-                               if (cancelMessage == value)
-                                       return;
-                               cancelMessage = value;
-                               NotifyValueChanged ("CancelMessage", cancelMessage);
-                       }
-               }
-               [DefaultValue("No")]
-               public virtual string NoMessage
-               {
-                       get { return noMessage; }
-                       set {
-                               if (noMessage == value)
-                                       return;
-                               noMessage = value;
-                               NotifyValueChanged ("NoMessage", noMessage);
-                       }
-               }
-               [DefaultValue("Information")]
-               public virtual Type MsgType
-               {
-                       get { return msgType; }
-                       set {
-                               if (msgType == value)
-                                       return;
-                               msgType = value;
-                               NotifyValueChanged ("MsgType", msgType);
-                               switch (msgType) {
-                               case Type.Information:
-                                       MsgIcon = "#Crow.Icons.iconInfo.svg";
-                                       Caption = "Informations";
-                                       OkMessage = "Ok";
-                                       NotifyValueChanged ("CancelButIsVisible", false);
-                                       NotifyValueChanged ("NoButIsVisible", false);
-                                       break;
-                               case Type.YesNo:
-                               case Type.YesNoCancel:
-                                       MsgIcon = "#Crow.Icons.question.svg";
-                                       Caption = "Choice";
-                                       OkMessage = "Yes";
-                                       NoMessage = "No";
-                                       NotifyValueChanged ("CancelButIsVisible", msgType == Type.YesNoCancel);
-                                       NotifyValueChanged ("NoButIsVisible", true);
-                                       break;
-                               case Type.Alert:
-                                       MsgIcon = "#Crow.Icons.IconAlerte.svg";
-                                       Caption = "Alert";
-                                       OkMessage = "Ok";
-                                       CancelMessage = "Cancel";
-                                       NotifyValueChanged ("CancelButIsVisible", true);
-                                       NotifyValueChanged ("NoButIsVisible", false);
-                                       break;
-                               case Type.Error:
-                                       MsgIcon = "#Crow.Icons.exit.svg";
-                                       Caption = "Error";
-                                       OkMessage = "Ok";
-                                       NotifyValueChanged ("CancelButIsVisible", false);
-                                       NotifyValueChanged ("NoButIsVisible", false);
-                                       break;
-                               }
-                       }
-               }
-
-               string msgIcon = null;
-               public string MsgIcon {
-                       get { return msgIcon; }
-                       set {
-                               if (value == MsgIcon)
-                                       return;
-                               msgIcon = value;
-                               NotifyValueChanged ("MsgIcon", MsgIcon);
-                       }
-               }
-               void onOkButtonClick (object sender, EventArgs e)
-               {
-                       Yes.Raise (this, null);
-                       close ();
-               }
-               void onNoButtonClick (object sender, EventArgs e)
-               {
-                       No.Raise (this, null);
-                       close ();
-               }
-               void onCancelButtonClick (object sender, EventArgs e)
-               {
-                       Cancel.Raise (this, null);
-                       close ();
-               }
-               public static MessageBox Show (Interface iface, Type msgBoxType, string message, string okMsg = "", string cancelMsg = ""){
-                       lock (iface.UpdateMutex) {
-                               MessageBox mb = new MessageBox (iface);
-                               mb.IFace.AddWidget (mb);
-                               mb.MsgType = msgBoxType;
-                               mb.Message = message;
-                               if (!string.IsNullOrEmpty(okMsg))
-                                       mb.OkMessage = okMsg;
-                               if (!string.IsNullOrEmpty(cancelMsg))
-                                       mb.CancelMessage = cancelMsg;
-                               return mb;
-                       }
-               }
-               public static MessageBox ShowModal (Interface iface, Type msgBoxType, string message){
-                       lock (iface.UpdateMutex) {
-                               MessageBox mb = new MessageBox (iface) {
-                                       Modal = true,
-                                       MsgType = msgBoxType,
-                                       Message = message
-                               };
-
-                               iface.AddWidget (mb);
-                               return mb;
-                       }
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/NumericControl.cs b/Crow/src/GraphicObjects/NumericControl.cs
deleted file mode 100644 (file)
index ec63fe8..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-//
-// NumericControl.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       public abstract class NumericControl : TemplatedControl
-       {
-               #region CTOR
-               protected NumericControl () : base(){}
-               public NumericControl (Interface iface) : base(iface)
-               {
-               }
-//             public NumericControl(double minimum, double maximum, double step)
-//                     : base()
-//             {
-//             }
-               #endregion
-
-               #region protected fields
-               protected double _actualValue, minValue, maxValue, smallStep, bigStep;
-               protected int _decimals;
-               #endregion
-
-               #region public properties
-               [DefaultValue(2)]
-               public int Decimals
-               {
-                       get { return _decimals; }
-                       set
-                       {
-                               if (value == _decimals)
-                                       return;
-                               _decimals = value;
-                               NotifyValueChanged("Decimals",  _decimals);
-                               RegisterForGraphicUpdate();
-                       }
-               }
-               [DefaultValue(0.0)]
-               public virtual double Minimum {
-                       get { return minValue; }
-                       set {
-                               if (minValue == value)
-                                       return;
-
-                               minValue = value;
-                               NotifyValueChanged ("Minimum", minValue);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(100.0)]
-               public virtual double Maximum
-               {
-                       get { return maxValue; }
-                       set {
-                               if (maxValue == value)
-                                       return;
-
-                               maxValue = value;
-                               NotifyValueChanged ("Maximum", maxValue);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(1.0)]
-               public virtual double SmallIncrement
-               {
-                       get { return smallStep; }
-                       set {
-                               if (smallStep == value)
-                                       return;
-
-                               smallStep = value;
-                               NotifyValueChanged ("SmallIncrement", smallStep);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(5.0)]
-               public virtual double LargeIncrement
-               {
-                       get { return bigStep; }
-                       set {
-                               if (bigStep == value)
-                                       return;
-
-                               bigStep = value;
-                               NotifyValueChanged ("LargeIncrement", bigStep);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(0.0)]
-               public virtual double Value
-               {
-                       get { return _actualValue; }
-                       set
-                       {
-                               if (value == _actualValue)
-                                       return;
-
-                               if (value < minValue)
-                                       _actualValue = minValue;
-                               else if (value > maxValue)
-                                       _actualValue = maxValue;
-                               else                    
-                                       _actualValue = value;
-
-                               _actualValue = Math.Round (_actualValue, _decimals);
-
-                               NotifyValueChanged("Value",  _actualValue);
-                               RegisterForGraphicUpdate();
-                       }
-               }
-               #endregion
-
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Popper.cs b/Crow/src/GraphicObjects/Popper.cs
deleted file mode 100644 (file)
index b6acabd..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-//
-// Popper.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-    public class Popper : TemplatedContainer
-    {
-               #region CTOR
-               protected Popper () : base(){}
-               public Popper (Interface iface) : base(iface){}
-               #endregion
-
-               bool _isPopped, _canPop;
-               Alignment popDirection;
-               Widget _content;
-               Measure popWidth, popHeight;
-
-               public event EventHandler Popped;
-               public event EventHandler Unpoped;
-
-               #region Public Properties
-               [DefaultValue("Fit")]
-               public virtual Measure PopWidth {
-                       get { return popWidth; }
-                       set {
-                               if (popWidth == value)
-                                       return;
-                               popWidth = value;
-                               NotifyValueChanged ("PopWidth", popWidth);
-                       }
-               }
-               [DefaultValue("Fit")]
-               public virtual Measure PopHeight {
-                       get { return popHeight; }
-                       set {
-                               if (popHeight == value)
-                                       return;
-                               popHeight = value;
-                               NotifyValueChanged ("PopHeight", popHeight);
-                       }
-               }
-               [DefaultValue(false)]
-               public bool IsPopped
-               {
-                       get { return _isPopped; }
-                       set
-                       {
-                               if (!_canPop & value)
-                                       return;                                 
-                               
-                               if (value == _isPopped)
-                                       return;
-
-                               _isPopped = value;
-
-                               NotifyValueChanged ("IsPopped", _isPopped);
-
-                               if (_isPopped)
-                                       onPop (this, null);
-                               else
-                                       onUnpop (this, null);
-
-                       }
-               }
-               [DefaultValue(true)]
-               public bool CanPop
-               {
-                       get { return _canPop; }
-                       set
-                       {
-                               if (value == _canPop)
-                                       return;
-
-                               _canPop = value;
-                               NotifyValueChanged ("CanPop", _canPop);
-                       }
-               }
-               [DefaultValue(Alignment.Bottom)]
-               public virtual Alignment PopDirection {
-                       get { return popDirection; }
-                       set {
-                               if (popDirection == value)
-                                       return;
-                               popDirection = value;
-                               NotifyValueChanged ("PopDirection", popDirection);
-                       }
-               }
-               #endregion
-
-               public override Widget Content {
-                       get { return _content; }
-                       set {
-                               if (_content != null) {
-                                       _content.LogicalParent = null;
-                                       //_content.isPopup = false;
-                                       _content.LayoutChanged -= _content_LayoutChanged;
-                               }
-
-                               _content = value;
-
-                               if (_content == null)
-                                       return;
-
-                               _content.LogicalParent = this;
-                               //_content.isPopup = true;
-                               _content.HorizontalAlignment = HorizontalAlignment.Left;
-                               _content.VerticalAlignment = VerticalAlignment.Top;
-                               _content.LayoutChanged += _content_LayoutChanged;
-                       }
-               }
-               void positionContent(LayoutingType lt){
-                       ILayoutable tc = Content.Parent;
-                       if (tc == null)
-                               return;
-                       Rectangle r = this.ScreenCoordinates (this.Slot);
-                       if (lt == LayoutingType.X) {
-                               if (popDirection.HasFlag (Alignment.Right)) {
-                                       if (r.Right + Content.Slot.Width > tc.ClientRectangle.Right)
-                                               Content.Left = r.Left - Content.Slot.Width;
-                                       else
-                                               Content.Left = r.Right;
-                               } else if (popDirection.HasFlag (Alignment.Left)) {
-                                       if (r.Left - Content.Slot.Width < tc.ClientRectangle.Left)
-                                               Content.Left = r.Right;
-                                       else
-                                               Content.Left = r.Left - Content.Slot.Width;
-                               } else {
-                                       if (Content.Slot.Width < tc.ClientRectangle.Width) {
-                                               if (r.Left + Content.Slot.Width > tc.ClientRectangle.Right)
-                                                       Content.Left = tc.ClientRectangle.Right - Content.Slot.Width;
-                                               else
-                                                       Content.Left = r.Left;
-                                       } else
-                                               Content.Left = 0;
-                               }
-                       }else if (lt == LayoutingType.Y) {
-                               if (Content.Slot.Height < tc.ClientRectangle.Height) {
-                                       if (PopDirection.HasFlag (Alignment.Bottom)) {
-                                               if (r.Bottom + Content.Slot.Height > tc.ClientRectangle.Bottom)
-                                                       Content.Top = r.Top - Content.Slot.Height;
-                                               else
-                                                       Content.Top = r.Bottom;
-                                       } else if (PopDirection.HasFlag (Alignment.Top)) {
-                                               if (r.Top - Content.Slot.Height < tc.ClientRectangle.Top)
-                                                       Content.Top = r.Bottom;
-                                               else
-                                                       Content.Top = r.Top - Content.Slot.Height;
-                                       } else
-                                               Content.Top = r.Top;
-                               }else
-                                       Content.Top = 0;
-                       }
-               }
-               protected void _content_LayoutChanged (object sender, LayoutingEventArgs e)
-               {
-                       if (e.LayoutType.HasFlag (LayoutingType.Width))
-                               positionContent (LayoutingType.X);
-                       if (e.LayoutType.HasFlag(LayoutingType.Height))
-                               positionContent (LayoutingType.Y);
-               }
-
-               #region GraphicObject overrides
-               public override void onMouseLeave (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseLeave (this, e);
-                       IsPopped = false;
-               }
-               public override bool MouseIsIn (Point m)
-               {                       
-                       if (Content?.Parent != null)
-                               if (Content.MouseIsIn (m))
-                                       return true;
-                       return base.MouseIsIn (m);
-               }
-               public override void checkHoverWidget (MouseMoveEventArgs e)
-               {
-                       if (IFace.HoverWidget != this) {
-                               IFace.HoverWidget = this;
-                               onMouseEnter (this, e);
-                       }
-                       if (Content != null){
-                               if (Content.Parent != null) {
-                                       if (Content.MouseIsIn (e.Position)) {
-                                               Content.checkHoverWidget (e);
-                                               return;
-                                       }
-                               }
-                       }
-                       base.checkHoverWidget (e);
-               }
-               #endregion
-
-               public virtual void onPop(object sender, EventArgs e)
-               {
-                       if (Content != null) {
-                               Content.Visible = true;
-                               if (Content.Parent == null)
-                                       IFace.AddWidget (Content);
-                               //if (Content.LogicalParent != this)
-                               Content.LogicalParent = this;
-                               IFace.PutOnTop (Content, true);
-                               _content_LayoutChanged (this, new LayoutingEventArgs (LayoutingType.Sizing));
-                       }
-                       Popped.Raise (this, e);
-               }
-               public virtual void onUnpop(object sender, EventArgs e)
-               {
-                       if (Content != null) {
-                               Content.Visible = false;
-                       }
-                       Unpoped.Raise (this, e);
-               }
-
-               protected override void Dispose (bool disposing)
-               {
-                       if (_content != null && disposing) {
-                               if (_content.Parent == null)
-                                       _content.Dispose ();
-                       }
-                       base.Dispose (disposing);
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/PrivateContainer.cs b/Crow/src/GraphicObjects/PrivateContainer.cs
deleted file mode 100644 (file)
index 7909a6d..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-//
-// PrivateContainer.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.Xml.Serialization;
-using System.ComponentModel;
-using Crow.Cairo;
-
-namespace Crow
-{
-       /// <summary>
-       /// Implement drawing and layouting for a single child, but
-       /// does not expose child to allow reuse of container
-       /// behaviour for widgets that have other xml hierarchy: example
-       /// TemplatedControl may have 3 children (template,templateItem,content) but
-       /// behave exactely as a container for layouting and drawing
-       /// </summary>
-       [DesignIgnore]
-       public class PrivateContainer : Widget
-       {
-               #region CTOR
-               protected PrivateContainer () : base(){}
-               public PrivateContainer (Interface iface) : base(iface){}
-               #endregion
-
-               #if DESIGN_MODE
-               public override bool FindByDesignID(string designID, out Widget go){
-                       go = null;
-                       if (base.FindByDesignID (designID, out go))
-                               return true;
-                       if (child == null)
-                               return false;
-                       return child.FindByDesignID (designID, out go);                                 
-               }
-               #endif
-               protected Widget child;
-               #if DEBUG_LOG
-               internal GraphicObject getTemplateRoot {
-                       get { return child; }
-               }
-               #endif
-
-               protected virtual void SetChild(Widget _child)
-               {
-
-                       if (child != null) {
-                               //check if HoverWidget is removed from Tree
-                               if (IFace.HoverWidget != null) {
-                                       if (this.Contains (IFace.HoverWidget))
-                                               IFace.HoverWidget = null;
-                               }
-                               contentSize = default(Size);
-                               child.LayoutChanged -= OnChildLayoutChanges;
-                               this.RegisterForGraphicUpdate ();
-                               child.Dispose ();
-                       }
-
-                       child = _child as Widget;
-
-                       if (child != null) {
-                               child.Parent = this;
-                               child.LayoutChanged += OnChildLayoutChanges;
-                               contentSize = child.Slot.Size;
-                               child.RegisteredLayoutings = LayoutingType.None;
-                               child.RegisterForLayouting (LayoutingType.Sizing);
-                       }
-               }
-               //dispose child if not null
-               protected virtual void deleteChild () {
-                       Widget g = child;
-                       SetChild (null);
-                       if (g != null)
-                               g.Dispose ();
-               }
-
-               #region GraphicObject Overrides
-
-               public override Widget FindByName (string nameToFind)
-               {
-                       if (Name == nameToFind)
-                               return this;
-
-                       return child == null ? null : child.FindByName (nameToFind);
-               }
-               public override bool Contains (Widget goToFind)
-               {
-                       return child == goToFind ? true : 
-                               child == null ? false : child.Contains(goToFind);
-               }
-               public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
-               {
-                       base.OnDataSourceChanged (this, e);
-                       if (child != null)
-                       if (child.localDataSourceIsNull & child.localLogicalParentIsNull)
-                               child.OnDataSourceChanged (child, e);
-               }
-               public override bool UpdateLayout (LayoutingType layoutType)
-               {
-                       if (child != null) {
-                               //force sizing to fit if sizing on children and child has stretched size
-                               switch (layoutType) {
-                               case LayoutingType.Width:
-                                       if (Width == Measure.Fit && child.Width.IsRelativeToParent)
-                                               child.Width = Measure.Fit;
-                                       break;
-                               case LayoutingType.Height:
-                                       if (Height == Measure.Fit && child.Height.IsRelativeToParent)
-                                               child.Height = Measure.Fit;
-                                       break;
-                               }
-                       }
-                       return base.UpdateLayout (layoutType);
-               }
-               public override void OnLayoutChanges (LayoutingType layoutType)
-               {
-                       base.OnLayoutChanges (layoutType);
-
-                       if (child == null)
-                               return;
-                       
-                       LayoutingType ltChild = LayoutingType.None;
-
-                       if (layoutType == LayoutingType.Width) {
-                               if (child.Width.IsRelativeToParent) {
-                                       ltChild |= LayoutingType.Width;
-                                       if (child.Width.Value < 100 && child.Left == 0)
-                                               ltChild |= LayoutingType.X;
-                               } else if (child.Left == 0)
-                                       ltChild |= LayoutingType.X;
-                       } else if (layoutType == LayoutingType.Height) {
-                               if (child.Height.IsRelativeToParent) {
-                                       ltChild |= LayoutingType.Height;
-                                       if (child.Height.Value < 100 && child.Top == 0)
-                                               ltChild |= LayoutingType.Y;
-                               } else if (child.Top == 0)
-                                               ltChild |= LayoutingType.Y;
-                       }
-                       if (ltChild == LayoutingType.None)
-                               return;
-                       child.RegisterForLayouting (ltChild);
-               }
-               public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
-               {                       
-                       Widget g = sender as Widget;
-
-                       if (arg.LayoutType == LayoutingType.Width) {
-                               if (Width != Measure.Fit)
-                                       return;
-                               contentSize.Width = g.Slot.Width;
-                               this.RegisterForLayouting (LayoutingType.Width);
-                       }else if (arg.LayoutType == LayoutingType.Height){
-                               if (Height != Measure.Fit)
-                                       return;
-                               contentSize.Height = g.Slot.Height;
-                               this.RegisterForLayouting (LayoutingType.Height);
-                       }
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       gr.Save ();
-
-                       if (ClipToClientRect) {
-                               //clip to client zone
-                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
-                               gr.Clip ();
-                       }
-
-                       if (child != null) {
-                               if (child.Visible)
-                                       child.Paint (ref gr);
-                       }
-                       gr.Restore ();
-               }
-               protected override void UpdateCache (Context ctx)
-               {
-                       Rectangle rb = Slot + Parent.ClientRectangle.Position;
-
-
-                       Context gr = new Context (bmp);
-
-                       if (!Clipping.IsEmpty) {
-                               for (int i = 0; i < Clipping.NumRectangles; i++)
-                                       gr.Rectangle(Clipping.GetRectangle(i));
-                               gr.ClipPreserve();
-                               gr.Operator = Operator.Clear;
-                               gr.Fill();
-                               gr.Operator = Operator.Over;
-
-                               onDraw (gr);
-                       }
-                               
-                       gr.Dispose ();
-
-                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
-                       ctx.Paint ();
-                       Clipping.Dispose();
-                       Clipping = new Region ();
-               }
-               #endregion
-
-               #region Mouse handling
-               public override void checkHoverWidget (MouseMoveEventArgs e)
-               {
-                       base.checkHoverWidget (e);
-
-                       if (child != null) 
-                               if (child.MouseIsIn (e.Position)) 
-                                       child.checkHoverWidget (e);
-               }
-               #endregion
-
-               protected override void Dispose (bool disposing)
-               {
-                       if (disposing && child != null)
-                               child.Dispose ();
-                       base.Dispose (disposing);
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/ProgressBar.cs b/Crow/src/GraphicObjects/ProgressBar.cs
deleted file mode 100644 (file)
index 20fadad..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// ProgressBar.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.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crow.Cairo;
-using System.Diagnostics;
-using System.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       
-       public class ProgressBar : NumericControl
-    {
-               #region CTOR
-               protected ProgressBar () : base(){}
-               public ProgressBar(Interface iface) : base(iface){}
-               #endregion
-
-               protected override void loadTemplate (Widget template)
-               {
-                       
-               }
-
-               #region GraphicObject overrides
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       if (Maximum == 0)
-                               return;
-
-                       Rectangle rBack = ClientRectangle;
-                       rBack.Width = (int)((double)rBack.Width / Maximum * Value);
-                       Foreground.SetAsSource (gr, rBack);
-
-                       CairoHelpers.CairoRectangle(gr,rBack,CornerRadius);
-                       gr.Fill();
-               }
-               #endregion
-    }
-}
diff --git a/Crow/src/GraphicObjects/RadioButton.cs b/Crow/src/GraphicObjects/RadioButton.cs
deleted file mode 100644 (file)
index d18971a..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// RadioButton.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.ComponentModel;
-using System.Xml.Serialization;
-
-namespace Crow
-{
-    public class RadioButton : TemplatedControl
-    {                  
-               bool isChecked;
-
-               #region CTOR
-               protected RadioButton () : base(){}
-               public RadioButton(Interface iface) : base(iface){}     
-               #endregion
-
-               public event EventHandler Checked;
-               public event EventHandler Unchecked;
-
-               #region GraphicObject overrides
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {                                               
-                       Group pg = Parent as Group;
-                       if (pg != null) {
-                               for (int i = 0; i < pg.Children.Count; i++) {
-                                       RadioButton c = pg.Children [i] as RadioButton;
-                                       if (c == null)
-                                               continue;
-                                       c.IsChecked = (c == this);
-                               }
-                       } else
-                               IsChecked = !IsChecked;
-
-                       base.onMouseDown (sender, e);
-               }
-               #endregion
-
-        [DefaultValue(false)]
-        public bool IsChecked
-        {
-                       get { return isChecked; }
-            set
-            {
-                               if (isChecked == value)
-                                       return;
-                               
-                               isChecked = value;
-
-                               NotifyValueChanged ("IsChecked", value);
-
-                               if (isChecked)
-                                       Checked.Raise (this, null);
-                               else
-                                       Unchecked.Raise (this, null);
-            }
-        }
-       }
-}
diff --git a/Crow/src/GraphicObjects/SaturationValueSelector.cs b/Crow/src/GraphicObjects/SaturationValueSelector.cs
deleted file mode 100644 (file)
index 779a6de..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-//
-// SaturationValueSelector.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 Crow.Cairo;
-using System.Xml.Serialization;
-
-namespace Crow
-{
-       [DesignIgnore]
-       public class SaturationValueSelector : ColorSelector
-       {
-               public SaturationValueSelector () : base(){}
-               public SaturationValueSelector (Interface iface) : base(iface)
-               {
-               }
-
-               double v, s;
-                               
-               public virtual double V {
-                       get { return v; }
-                       set {
-                               if (v == value)
-                                       return;
-                               v = value;
-                               NotifyValueChanged ("V", v);
-                               mousePos.Y = (int)Math.Floor((1.0-v) * (double)ClientRectangle.Height);
-
-                               RegisterForRedraw ();
-                       }
-               }
-               
-               public virtual double S {
-                       get { return s; }
-                       set {
-                               if (s == value)
-                                       return;
-                               s = value;
-                               NotifyValueChanged ("S", s);
-                               mousePos.X = (int)Math.Floor(s * (double)ClientRectangle.Width);
-
-                               RegisterForRedraw ();
-                       }
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       Rectangle r = ClientRectangle;
-
-                       if (Foreground != null) {//TODO:test if null should be removed
-                               Foreground.SetAsSource (gr, r);
-                               CairoHelpers.CairoRectangle (gr, r, CornerRadius);
-                               gr.Fill ();
-                       }
-
-                       Crow.Gradient grad = new Gradient (Gradient.Type.Horizontal);
-                       grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 1, 1, 1)));
-                       grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, 1, 1, 0)));
-                       grad.SetAsSource (gr, r);
-                       CairoHelpers.CairoRectangle (gr, r, CornerRadius);
-                       gr.Fill();
-                       grad = new Gradient (Gradient.Type.Vertical);
-                       grad.Stops.Add (new Gradient.ColorStop (0, new Color (0, 0, 0, 0)));
-                       grad.Stops.Add (new Gradient.ColorStop (1, new Color (0, 0, 0, 1)));
-                       grad.SetAsSource (gr, r);
-                       CairoHelpers.CairoRectangle (gr, r, CornerRadius);
-                       gr.Fill();
-
-
-                       gr.Arc (mousePos.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
-                       gr.SetSourceColor (Color.Black);
-                       gr.LineWidth = 2.0;
-                       gr.StrokePreserve ();
-                       gr.SetSourceColor (Color.White);
-                       gr.LineWidth = 1.0;
-                       gr.Stroke ();
-               }
-
-               //public override void Paint (ref Context ctx)
-               //{
-               //      base.Paint (ref ctx);
-
-               //      Rectangle rb = Slot + Parent.ClientRectangle.Position;
-               //      ctx.Save ();
-
-               //      ctx.Translate (rb.X, rb.Y);
-
-               //      ctx.SetSourceColor (Color.DimGrey);
-               //      ctx.Arc (mousePos.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
-               //      ctx.LineWidth = 0.5;
-               //      ctx.Stroke ();
-               //      ctx.Translate (-0.5, -0.5);
-               //      ctx.Arc (mousePos.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
-               //      ctx.SetSourceColor (Color.White);
-               //      ctx.Stroke ();
-
-               //      ctx.Restore ();
-               //}
-
-               protected override void updateMouseLocalPos (Point mPos)
-               {
-                       base.updateMouseLocalPos (mPos);
-
-                       Rectangle cb = ClientRectangle;
-                       s = (double)mousePos.X / (double)cb.Width;
-                       v = 1.0 - (double)mousePos.Y / (double)cb.Height;
-                       NotifyValueChanged ("S", s);
-                       NotifyValueChanged ("V", v);
-
-                       RegisterForRedraw ();
-               }
-               public override void OnLayoutChanges (LayoutingType layoutType)
-               {
-                       base.OnLayoutChanges (layoutType);
-                       switch (layoutType) {
-                       case LayoutingType.Width:
-                               mousePos.X = (int)Math.Floor(s * (double)ClientRectangle.Width);
-                               break;
-                       case LayoutingType.Height:
-                               mousePos.Y = (int)Math.Floor((1.0-v) * (double)ClientRectangle.Height);
-                               break;
-                       }
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/ScrollBar.cs b/Crow/src/GraphicObjects/ScrollBar.cs
deleted file mode 100644 (file)
index cf6201e..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-//
-// ScrollBar.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       /// <summary>
-       /// templeted numeric control
-       /// </summary>
-       public class ScrollBar : NumericControl
-       {
-               //TODO:could be replaced by a template for a Slider
-
-               Orientation _orientation;
-               int _cursorSize;
-
-               #region CTOR
-               protected ScrollBar () : base(){}
-               public ScrollBar(Interface iface) : base(iface) {}
-               #endregion
-
-               [DefaultValue(Orientation.Vertical)]
-               public virtual Orientation Orientation
-               {
-                       get { return _orientation; }
-                       set {                           
-                               if (_orientation == value)
-                                       return;
-                               _orientation = value;
-                               NotifyValueChanged ("Orientation", _orientation);
-                               if (_orientation == Orientation.Horizontal)
-                                       NotifyValueChanged ("ScrollBackShape", "M 1.5,3.5 L 6.5,0.5 L 6.5,6.5 Z");
-                               else
-                                       NotifyValueChanged ("ScrollBackShape", "M 4.5,0.5 L 9.5,9.5 L 0.5,9.5 Z");
-
-                RegisterForGraphicUpdate ();
-                       }
-               }
-               [DefaultValue(20)]
-               public virtual int CursorSize {
-                       get { return _cursorSize; }
-                       set {
-                               if (_cursorSize == value)
-                                       return;
-                               _cursorSize = value;
-                               RegisterForGraphicUpdate ();
-                               NotifyValueChanged ("CursorSize", _cursorSize);
-                       }
-               }
-               public void onScrollBack (object sender, MouseButtonEventArgs e)
-               {
-                       Value -= SmallIncrement;
-               }
-               public void onScrollForth (object sender, MouseButtonEventArgs e)
-               {
-                       Value += SmallIncrement;
-               }
-
-               public void onSliderValueChange(object sender, ValueChangeEventArgs e){
-                       if (e.MemberName == "Value")
-                               Value = Convert.ToDouble(e.NewValue);
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/Scroller.cs b/Crow/src/GraphicObjects/Scroller.cs
deleted file mode 100644 (file)
index 7bdb7d3..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-//
-// Scroller.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.Xml.Serialization;
-using System.ComponentModel;
-using System.Diagnostics;
-using Crow.Cairo;
-
-namespace Crow
-{
-       /// <summary>
-       /// scrolling surface, to be contained in a smaller container in which it will be scrolled
-       /// </summary>
-       public class Scroller : Container
-       {
-               #region CTOR
-               protected Scroller () : base(){}
-               public Scroller (Interface iface) : base(iface){}
-               #endregion
-
-               //public event EventHandler<ScrollingEventArgs> Scrolled;
-
-               int scrollX, scrollY, maxScrollX, maxScrollY, scrollSpeed;
-
-               /// <summary>
-               /// if true, key stroke are handled in derrived class
-               /// </summary>
-               protected bool KeyEventsOverrides = false;
-
-               #region public properties
-               /// <summary> Horizontal Scrolling Position </summary>
-               [DefaultValue(0)]
-               public virtual int ScrollX {
-                       get { return scrollX; }
-                       set {
-                               if (scrollX == value)
-                                       return;
-
-                               int newS = value;
-                               if (newS < 0)
-                                       newS = 0;
-                               else if (newS > maxScrollX)
-                                       newS = maxScrollX;
-
-                               if (newS == scrollX)
-                                       return;
-
-                               scrollX = value;
-
-                               NotifyValueChanged ("ScrollX", scrollX);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary> Vertical Scrolling Position </summary>
-               [DefaultValue(0)]
-               public virtual int ScrollY {
-                       get { return scrollY; }
-                       set {
-                               if (scrollY == value)
-                                       return;
-
-                               int newS = value;
-                               if (newS < 0)
-                                       newS = 0;
-                               else if (newS > maxScrollY)
-                                       newS = maxScrollY;
-
-                               if (newS == scrollY)
-                                       return;
-
-                               scrollY = value;
-
-                               NotifyValueChanged ("ScrollY", scrollY);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary> Horizontal Scrolling maximum value </summary>
-               [DefaultValue(0)]
-               public virtual int MaxScrollX {
-                       get { return maxScrollX; }
-                       set {
-                               if (maxScrollX == value)
-                                       return;
-
-                               maxScrollX = value;
-
-                               if (scrollX > maxScrollX)
-                                       ScrollX = maxScrollX;
-
-                               NotifyValueChanged ("MaxScrollX", maxScrollX);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary> Vertical Scrolling maximum value </summary>
-               [DefaultValue(0)]
-               public virtual int MaxScrollY {
-                       get { return maxScrollY; }
-                       set {
-                               if (maxScrollY == value)
-                                       return;
-
-                               maxScrollY = value;
-
-                               if (scrollY > maxScrollY)
-                                       ScrollY = maxScrollY;
-
-                               NotifyValueChanged ("MaxScrollY", maxScrollY);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary> Mouse Wheel Scrolling multiplier </summary>
-               [DefaultValue(50)]
-               public virtual int ScrollSpeed {
-                       get { return scrollSpeed; }
-                       set {
-                               if (scrollSpeed == value)
-                                       return;
-
-                               scrollSpeed = value;
-
-                               NotifyValueChanged ("ScrollSpeed", scrollSpeed);
-                       }
-               }
-               #endregion
-
-               public override void SetChild (Widget _child)
-               {
-                       Group g = child as Group;
-                       if (g != null)
-                               g.ChildrenCleared -= onChildListCleared;
-                       
-                       base.SetChild (_child);
-
-                       g = _child as Group;
-                       if (g != null)
-                               g.ChildrenCleared += onChildListCleared;                        
-               }
-               public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
-               {
-                       base.OnChildLayoutChanges (sender, arg);
-                       updateMaxScroll (arg.LayoutType);
-               }
-
-
-               #region GraphicObject Overrides
-               public override Rectangle ScreenCoordinates (Rectangle r)
-               {
-                       return base.ScreenCoordinates (r) - new Point((int)ScrollX,(int)ScrollY);
-               }
-               public override bool PointIsIn (ref Point m)
-               {
-                       if (!base.PointIsIn(ref m))
-                               return false;
-                       if (!Slot.ContainsOrIsEqual (m) || child==null)
-                               return false;
-                       m += new Point (ScrollX, ScrollY);
-                       return true;
-               }
-               public override void RegisterClip (Rectangle clip)
-               {
-                       base.RegisterClip (clip - new Point(ScrollX,ScrollY));
-               }
-               public override void OnLayoutChanges (LayoutingType layoutType)
-               {
-                       base.OnLayoutChanges (layoutType);
-
-                       if (layoutType == LayoutingType.Height)
-                               NotifyValueChanged ("PageHeight", Slot.Height);
-                       else if (layoutType == LayoutingType.Width)
-                               NotifyValueChanged ("PageWidth", Slot.Width);
-                       else
-                               return;
-                       updateMaxScroll(layoutType);
-               }
-               protected override void onDraw (Context gr)
-               {
-                       Rectangle rBack = new Rectangle (Slot.Size);
-
-                       Background.SetAsSource (gr, rBack);
-                       CairoHelpers.CairoRectangle(gr,rBack, CornerRadius);
-                       gr.Fill ();
-
-                       gr.Save ();
-                       if (ClipToClientRect) {
-                               //clip to scrolled client zone
-                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
-                               gr.Clip ();
-                       }
-
-                       gr.Translate (-ScrollX, -ScrollY);
-                       if (child != null)
-                               child.Paint (ref gr);
-                       gr.Restore ();
-               }
-
-               #region Mouse & Keyboard
-               /// <summary> Process scrolling vertically, or if shift is down, vertically </summary>
-               public override void onMouseWheel (object sender, MouseWheelEventArgs e)
-               {
-                       if (IFace.Shift)
-                               ScrollX += e.Delta * ScrollSpeed;
-                       else
-                               ScrollY -= e.Delta * ScrollSpeed;
-                       e.Handled = true;
-                       base.onMouseWheel (sender, e);
-               }
-               /// <summary> Process scrolling with arrow keys, home and end keys. </summary>
-               public override void onKeyDown (object sender, KeyEventArgs e)
-               {
-                       base.onKeyDown (sender, e);
-
-                       if (KeyEventsOverrides)
-                               return;
-
-                       switch (e.Key) {
-                       case Key.Up:
-                               ScrollY--;
-                               break;
-                       case Key.Down:
-                               ScrollY++;
-                               break;
-                       case Key.Left:
-                               ScrollX--;
-                               break;
-                       case Key.Right:
-                               ScrollX++;
-                               break;
-                       case Key.Home:
-                               ScrollX = 0;
-                               ScrollY = 0;
-                               break;
-                       case Key.End:
-                               ScrollX = MaxScrollX;
-                               ScrollY = MaxScrollY;
-                               break;
-                       }
-               }
-               #endregion
-
-               #endregion
-
-               void updateMaxScroll (LayoutingType lt){
-                       if (Child == null) {
-                               MaxScrollX = 0;
-                               MaxScrollY = 0;
-                               return;
-                       }
-
-                       Rectangle cb = ClientRectangle;
-
-                       if (lt == LayoutingType.Height) {
-                               MaxScrollY = child.Slot.Height - cb.Height;
-                               if (child.Slot.Height > 0)
-                                       NotifyValueChanged ("ChildHeightRatio", Slot.Height * Slot.Height / child.Slot.Height);                 
-                       } else if (lt == LayoutingType.Width) {
-                               MaxScrollX = child.Slot.Width - cb.Width;
-                               if (child.Slot.Width > 0)
-                                       NotifyValueChanged ("ChildWidthRatio", Slot.Width * Slot.Width / child.Slot.Width);
-                       }
-               }
-               void onChildListCleared(object sender, EventArgs e){
-                       ScrollY = 0;
-                       ScrollX = 0;
-               }
-
-
-    }
-}
diff --git a/Crow/src/GraphicObjects/ScrollingObject.cs b/Crow/src/GraphicObjects/ScrollingObject.cs
deleted file mode 100644 (file)
index 1280489..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-//
-// ScrollingObject.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.Xml.Serialization;
-using System.ComponentModel;
-using System.Collections;
-using Crow.Cairo;
-
-
-namespace Crow
-{
-       /// <summary>
-       /// generic class to build scrolling control in both directions
-       /// </summary>
-       [DesignIgnore]
-       public class ScrollingObject : Widget
-       {
-               #region CTOR
-               protected ScrollingObject ():base(){}
-               public ScrollingObject (Interface iface):base(iface){}
-               #endregion
-
-               int scrollX, scrollY, maxScrollX, maxScrollY, mouseWheelSpeed;
-
-               /// <summary>
-               /// if true, key stroke are handled in derrived class
-               /// </summary>
-               protected bool KeyEventsOverrides = false;
-
-               /// <summary> Horizontal Scrolling Position </summary>
-               [DefaultValue(0)]
-               public virtual int ScrollX {
-                       get { return scrollX; }
-                       set {
-                               if (scrollX == value)
-                                       return;
-
-                               int newS = value;
-                               if (newS < 0)
-                                       newS = 0;
-                               else if (newS > maxScrollX)
-                                       newS = maxScrollX;
-
-                               if (newS == scrollX)
-                                       return;
-
-                               scrollX = newS;
-
-                               NotifyValueChanged ("ScrollX", scrollX);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary> Vertical Scrolling Position </summary>
-               [DefaultValue(0)]
-               public virtual int ScrollY {
-                       get { return scrollY; }
-                       set {
-                               if (scrollY == value)
-                                       return;
-
-                               int newS = value;
-                               if (newS < 0)
-                                       newS = 0;
-                               else if (newS > maxScrollY)
-                                       newS = maxScrollY;
-
-                               if (newS == scrollY)
-                                       return;
-
-                               scrollY = newS;
-
-                               NotifyValueChanged ("ScrollY", scrollY);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary> Horizontal Scrolling maximum value </summary>
-               [DefaultValue(0)]
-               public virtual int MaxScrollX {
-                       get { return maxScrollX; }
-                       set {
-                               if (maxScrollX == value)
-                                       return;
-
-                               maxScrollX = value;
-
-                               if (scrollX > maxScrollX)
-                                       ScrollX = maxScrollX;
-                               
-                               NotifyValueChanged ("MaxScrollX", maxScrollX);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary> Vertical Scrolling maximum value </summary>
-               [DefaultValue(0)]
-               public virtual int MaxScrollY {
-                       get { return maxScrollY; }
-                       set {
-                               if (maxScrollY == value)
-                                       return;
-
-                               maxScrollY = value;
-
-                               if (scrollY > maxScrollY)
-                                       ScrollY = maxScrollY;
-
-                               NotifyValueChanged ("MaxScrollY", maxScrollY);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary> Mouse Wheel Scrolling multiplier </summary>
-               [DefaultValue(1)]
-               public virtual int MouseWheelSpeed {
-                       get { return mouseWheelSpeed; }
-                       set {
-                               if (mouseWheelSpeed == value)
-                                       return;
-                               
-                               mouseWheelSpeed = value;
-
-                               NotifyValueChanged ("MouseWheelSpeed", mouseWheelSpeed);
-                       }
-               }
-
-               /// <summary> Process scrolling vertically, or if shift is down, vertically </summary>
-               public override void onMouseWheel (object sender, MouseWheelEventArgs e)
-               {
-                       base.onMouseWheel (sender, e);
-                       if (IFace.Shift)
-                               ScrollX += e.Delta * MouseWheelSpeed;
-                       else
-                               ScrollY -= e.Delta * MouseWheelSpeed;
-               }
-               /// <summary> Process scrolling with arrow keys, home and end keys. </summary>
-               public override void onKeyDown (object sender, KeyEventArgs e)
-               {
-                       base.onKeyDown (sender, e);
-
-                       if (KeyEventsOverrides)
-                               return;
-
-                       switch (e.Key) {
-                       case Key.Up:
-                               ScrollY--;
-                               break;
-                       case Key.Down:
-                               ScrollY++;
-                               break;
-                       case Key.Left:
-                               ScrollX--;
-                               break;
-                       case Key.Right:
-                               ScrollX++;
-                               break;
-                       case Key.Home:
-                               ScrollX = 0;
-                               ScrollY = 0;
-                               break;
-                       case Key.End:
-                               ScrollX = MaxScrollX;
-                               ScrollY = MaxScrollY;
-                               break;
-                       }
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Shape.cs b/Crow/src/GraphicObjects/Shape.cs
deleted file mode 100644 (file)
index 952c373..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.ComponentModel;
-using System.IO;
-using System.Text;
-using Crow.Cairo;
-
-namespace Crow
-{
-       public class PathParser : StringReader
-       {
-               public PathParser (string str) : base (str) {}
-
-               double readDouble () {
-                       StringBuilder tmp = new StringBuilder();
-
-                       while (Peek () >= 0) {                          
-                               char c = (char)Read();
-                               if (c.IsWhiteSpaceOrNewLine()) {
-                                       if (tmp.Length == 0)
-                                               continue;
-                                       else
-                                               break;
-                               } else if (c == ',')
-                                       break;                          
-                               tmp.Append (c);
-                       }
-                       return double.Parse (tmp.ToString ());
-               }
-               public void Draw (Context gr) {
-                       while (Peek () >= 0) {
-                               char c = (char)Read ();
-                               if (c.IsWhiteSpaceOrNewLine ())
-                                       continue;
-                               switch (c) {
-                               case 'M':
-                                       gr.MoveTo (readDouble (), readDouble ());
-                                       break;
-                               case 'm':
-                                       gr.RelMoveTo (readDouble (), readDouble ());
-                                       break;
-                               case 'L':
-                                       gr.LineTo (readDouble (), readDouble ());
-                                       break;
-                               case 'l':
-                                       gr.RelLineTo (readDouble (), readDouble ());
-                                       break;
-                               case 'C':
-                                       gr.CurveTo (readDouble (), readDouble (), readDouble (), readDouble (), readDouble (), readDouble ());
-                                       break;
-                               case 'c':
-                                       gr.RelCurveTo (readDouble (), readDouble (), readDouble (), readDouble (), readDouble (), readDouble ());
-                                       break;
-                               case 'Z':
-                                       gr.ClosePath ();
-                                       break;
-                               case 'F':
-                                       gr.Fill ();
-                                       break;
-                               case 'G':
-                                       gr.Stroke ();
-                                       break;
-                               default:
-                                       throw new Exception ("Invalid character in path string of Shape control");
-                               }
-                       }                       
-               }
-       }
-       public class Shape : Widget
-       {
-               #region CTOR
-               protected Shape () : base() {}
-               public Shape (Interface iface) : base (iface) {}
-               #endregion
-
-               string path;
-               double strokeWidth;
-        Size size;
-
-               public string Path {
-                       get { return path; }
-                       set {
-                               if (path == value)
-                                       return;
-                               path = value;
-                               contentSize = default (Size);
-                               NotifyValueChanged ("Path", path);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               [DefaultValue(1.0)]
-               public double StokeWidth {
-                       get { return strokeWidth; }
-                       set {
-                               if (strokeWidth == value)
-                                       return;
-                               strokeWidth = value;
-                               contentSize = default (Size);
-                               NotifyValueChanged ("StrokeWidth", strokeWidth);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-        [DefaultValue("0,0")]
-        public Size Size
-        {
-            get { return size; }
-            set
-            {
-                if (size == value)
-                    return;
-                size = value;
-                contentSize = default(Size);
-                NotifyValueChanged("Size", size);
-                RegisterForLayouting(LayoutingType.Sizing);
-            }
-        }
-        protected override void onDraw(Context gr)
-        {
-
-            if (string.IsNullOrEmpty(path))
-                return;
-
-            gr.Save();
-
-            Rectangle r = ClientRectangle;
-
-
-            double sx = (double)r.Width / (double)(contentSize.Width == 0? size.Width : contentSize.Width);
-            double sy = (double)r.Height / (double)(contentSize.Height == 0 ? size.Height : contentSize.Height);            
-
-            gr.Translate(r.Left, r.Top);
-            gr.Scale (sx,sy);
-
-                       using (PathParser parser = new PathParser (path))
-                               parser.Draw (gr);
-                               
-                       Background.SetAsSource (gr, r);
-                       gr.FillPreserve ();
-                       gr.LineWidth = strokeWidth;
-                       Foreground.SetAsSource (gr, r);
-                       gr.Stroke ();
-            gr.Restore();
-               }
-
-
-               protected override int measureRawSize (LayoutingType lt)
-               {
-                       if ((lt == LayoutingType.Width && contentSize.Width == 0) || (lt == LayoutingType.Height && contentSize.Height == 0)) {
-                if (size != default(Size))
-                    contentSize = size;
-                else
-                {
-                    using (Surface drawing = new ImageSurface(Format.A1, 1, 1))
-                    {
-                        using (Context ctx = new Context(drawing))
-                        {
-                                                       using (PathParser parser = new PathParser (path))
-                                                               parser.Draw (ctx);                                                              
-                            Rectangle r = ctx.StrokeExtents();
-                            contentSize = new Size(r.Right, r.Bottom);
-                        }
-                    }
-                }
-                       }
-                       return lt == LayoutingType.Width ?
-                               contentSize.Width + 2 * Margin: contentSize.Height + 2 * Margin;
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Slider.cs b/Crow/src/GraphicObjects/Slider.cs
deleted file mode 100644 (file)
index e4942b2..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-//
-// Slider.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 Crow.Cairo;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using System.Diagnostics;
-
-namespace Crow
-{
-       /// <summary>
-       /// templated numeric control to select a value
-       /// by slidding a cursor
-       /// </summary>
-       public class Slider : NumericControl
-    {
-               #region CTOR
-               protected Slider() : base(){}
-               public Slider(Interface iface) : base(iface)
-               {}
-//             public Slider(double minimum, double maximum, double step)
-//                     : base(minimum,maximum,step)
-//             {
-//             }
-               #endregion
-
-               #region implemented abstract members of TemplatedControl
-
-               protected override void loadTemplate (Widget template = null)
-               {
-                       
-               }
-
-               #endregion
-
-               #region private fields
-        Rectangle cursor;
-               int _cursorSize;
-               Fill _cursorColor;
-               Orientation _orientation;
-               bool holdCursor = false;
-               #endregion
-
-               protected double unity;
-
-               #region Public properties
-               [DefaultValue("vgradient|0:White|0,1:LightGrey|0,9:LightGrey|1:DimGrey")]
-               public virtual Fill CursorColor {
-                       get { return _cursorColor; }
-                       set {
-                               if (_cursorColor == value)
-                                       return;
-                               _cursorColor = value;
-                               RegisterForRedraw ();
-                               NotifyValueChanged ("CursorColor", _cursorColor);
-                       }
-               }
-               [DefaultValue(20)]
-               public virtual int CursorSize {
-                       get { return _cursorSize; }
-                       set {
-                               if (_cursorSize == value || value < 8)
-                                       return;
-                               _cursorSize = value;
-                               RegisterForGraphicUpdate ();
-                               NotifyValueChanged ("CursorSize", _cursorSize);
-                       }
-               }
-               [DefaultValue(Orientation.Horizontal)]
-               public virtual Orientation Orientation
-               {
-                       get { return _orientation; }
-                       set { 
-                               if (_orientation == value)
-                                       return;
-                               _orientation = value; 
-
-                               RegisterForLayouting (LayoutingType.All);
-                               NotifyValueChanged ("Orientation", _orientation);
-                       }
-               }
-               #endregion
-
-               //[DefaultValue(10.0)]
-               //public override double Maximum {
-               //      get { return base.Maximum; }
-               //      set {                           
-               //              if (value == base.Maximum)
-               //                      return;
-               //              base.Maximum = value;
-               //              LargeIncrement = base.Maximum / 10.0;
-               //              SmallIncrement = LargeIncrement / 5.0;
-               //      }
-               //}
-
-               #region GraphicObject Overrides
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       if (Maximum <= 0)
-                               return;
-
-                       computeCursorPosition ();
-
-                       Rectangle r = ClientRectangle;
-                       PointD pStart;
-                       PointD pEnd;
-                       if (_orientation == Orientation.Horizontal) {
-                               pStart = r.TopLeft + new Point (_cursorSize / 2, r.Height / 2);
-                               pEnd = r.TopRight + new Point (-_cursorSize / 2, r.Height / 2);
-                               pStart.Y += 0.5;
-                               pEnd.Y += 0.5;
-                       } else {
-                               pStart = r.TopLeft + new Point (r.Width / 2, _cursorSize / 2);
-                               pEnd = r.BottomLeft + new Point (r.Width / 2,- _cursorSize / 2);
-                               pStart.X += 0.5;
-                               pEnd.X += 0.5;
-
-                       }
-
-            Background.SetAsSource(gr, r);
-            gr.Rectangle (r);
-            gr.Fill ();
-
-                       DrawGraduations (gr, pStart,pEnd);
-
-                       DrawCursor (gr, cursor);
-               }
-               #endregion
-
-               protected virtual void DrawGraduations(Context gr, PointD pStart, PointD pEnd)
-               {
-                       Foreground.SetAsSource (gr);
-
-                       gr.LineWidth = 1;
-                       gr.MoveTo(pStart);
-                       gr.LineTo(pEnd);
-
-                       gr.Stroke();
-
-               }
-               protected virtual void DrawCursor(Context gr, Rectangle _cursor)
-               {
-                       CairoHelpers.CairoRectangle (gr, _cursor, CornerRadius);
-            Foreground.SetAsSource(gr, _cursor);
-            gr.StrokePreserve();
-            CursorColor.SetAsSource(gr, _cursor);
-            gr.Fill();
-               }
-
-        void computeCursorPosition()
-        {            
-            Rectangle r = ClientRectangle;
-                       PointD p1; 
-
-                       if (_orientation == Orientation.Horizontal) {
-                               cursor = new Rectangle (new Size (_cursorSize, (int)(r.Height)));
-                               p1 = r.TopLeft + new Point (_cursorSize / 2, r.Height / 2);
-                               unity = (double)(r.Width - _cursorSize) / (Maximum - Minimum);
-                               cursor.TopLeft = new Point (r.Left + (int)((Value - Minimum) * unity),
-                                       (int)(p1.Y - cursor.Height / 2));
-                       } else {
-                               cursor = new Rectangle (new Size ((int)(r.Width), _cursorSize));
-                               p1 = r.TopLeft + new Point (r.Width / 2, _cursorSize / 2);
-                               unity = (double)(r.Height - _cursorSize) / (Maximum - Minimum);
-                               cursor.TopLeft = new Point ((int)(p1.X - r.Width / 2),
-                                       r.Top + (int)((Value - Minimum) * unity));                              
-                       }
-                       //cursor.Inflate (-1);
-        }
-               Point mouseDownInit;
-               double mouseDownInitValue;
-
-               #region mouse handling
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseDown (sender, e);
-                       mouseDownInit = ScreenPointToLocal (e.Position);
-                       mouseDownInitValue = Value;
-                       Rectangle cursInScreenCoord = ScreenCoordinates (cursor + Slot.Position);
-                       if (cursInScreenCoord.ContainsOrIsEqual (e.Position)){
-//                             Rectangle r = ClientRectangle;
-//                             if (r.Width - _cursorSize > 0) {
-//                                     double unit = (Maximum - Minimum) / (double)(r.Width - _cursorSize);
-//                                     mouseDownInit += new Point ((int)(Value / unit), (int)(Value / unit));
-//                             }
-                               holdCursor = true;
-                       }else if (_orientation == Orientation.Horizontal) {
-                               if (e.Position.X < cursInScreenCoord.Left)
-                                       Value -= LargeIncrement;
-                               else
-                                       Value += LargeIncrement;
-                       } else {
-                               if (e.Position.Y < cursInScreenCoord.Top)
-                                       Value -= LargeIncrement;
-                               else
-                                       Value += LargeIncrement;
-                       }
-               }
-               public override void onMouseUp (object sender,MouseButtonEventArgs e)
-               {
-                       base.onMouseUp (sender, e);
-
-                       holdCursor = false;
-               }
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       if (holdCursor) {                               
-                               Point m = ScreenPointToLocal (e.Position) - mouseDownInit;
-                               Rectangle r = ClientRectangle;
-
-                               if (_orientation == Orientation.Horizontal) {
-                                       if (r.Width - _cursorSize == 0)
-                                               return;                                 
-                                       double unit = (Maximum - Minimum) / (double)(r.Width - _cursorSize);
-                                       double tmp = mouseDownInitValue + (double)m.X * unit;
-                                       tmp -= tmp % SmallIncrement;
-                                       Value = tmp;
-                               } else {
-                                       if (r.Height - _cursorSize == 0)
-                                               return;                                 
-                                       double unit = (Maximum - Minimum) / (double)(r.Height - _cursorSize);
-                                       double tmp = mouseDownInitValue + (double)m.Y * unit;
-                                       tmp -= tmp % SmallIncrement;
-                                       Value = tmp;
-                               }
-                       }
-                       
-                       base.onMouseMove (sender, e);
-               }
-               #endregion
-    }
-}
diff --git a/Crow/src/GraphicObjects/Spinner.cs b/Crow/src/GraphicObjects/Spinner.cs
deleted file mode 100644 (file)
index 8a3bcd6..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-namespace Crow
-{
-       /// <summary>
-       /// templated control for selecting a numeric value by clicking on
-       /// up and down buttons
-       /// </summary>
-       public class Spinner : NumericControl
-       {
-               #region CTOR
-               protected Spinner() : base(){}
-               public Spinner (Interface iface) : base(iface)
-               {
-               }
-               #endregion
-
-               void onUp (object sender, MouseButtonEventArgs e)
-               {
-                       Value += this.SmallIncrement;
-               }
-               void onDown (object sender, MouseButtonEventArgs e)
-               {
-                       Value -= this.SmallIncrement;
-               }
-
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Splitter.cs b/Crow/src/GraphicObjects/Splitter.cs
deleted file mode 100644 (file)
index e3f2161..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-//
-// Splitter.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.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       /// <summary>
-       /// control to add between children of a Stack to allow them to be resized
-       /// with the pointer
-       /// </summary>
-       public class Splitter : Widget
-       {
-               #region CTOR
-               protected Splitter() : base(){}
-               public Splitter (Interface iface) : base(iface){}
-               #endregion
-
-               int thickness;
-
-               [DefaultValue(1)]
-               public virtual int Thickness {
-                       get { return thickness; }
-                       set {
-                               if (thickness == value)
-                                       return;
-                               thickness = value; 
-                               NotifyValueChanged ("Thickness", thickness);
-                               RegisterForLayouting (LayoutingType.Sizing);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-
-               Unit u1, u2;
-               int init1 = -1, init2 = -1, delta = 0, min1, min2, max1 , max2;
-               Widget go1 = null, go2 = null;
-
-               void initSplit(Measure m1, int size1, Measure m2, int size2){
-                       if (m1 != Measure.Stretched) {
-                               init1 = size1;
-                               u1 = m1.Units;
-                       }
-                       if (m2 != Measure.Stretched) {
-                               init2 = size2;
-                               u2 = m2.Units;
-                       }
-               }
-               void convertSizeInPix(Widget g1){
-
-               }
-
-               #region GraphicObject override
-               public override ILayoutable Parent {
-                       get { return base.Parent; }
-                       set {
-                               if (value != null) {                    
-                                       GenericStack gs = value as GenericStack;
-                                       if (gs == null)
-                                               throw new Exception ("Splitter may only be chil of stack");
-                                       
-                               }
-                               base.Parent = value;
-                       }
-               }
-               public override void onMouseEnter (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseEnter (sender, e);
-                       if ((Parent as GenericStack).Orientation == Orientation.Horizontal)
-                               IFace.MouseCursor = MouseCursor.H;
-                       else
-                               IFace.MouseCursor = MouseCursor.V;
-               }
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseDown (sender, e);
-                       go1 = go2 = null;
-                       init1 = init2 = -1;
-                       delta = 0;
-
-                       GenericStack gs = Parent as GenericStack;
-                       int ptrSplit = gs.Children.IndexOf (this);
-                       if (ptrSplit == 0 || ptrSplit == gs.Children.Count - 1)
-                               return;
-
-                       go1 = gs.Children [ptrSplit - 1];
-                       go2 = gs.Children [ptrSplit + 1];
-
-                       if (gs.Orientation == Orientation.Horizontal) {
-                               initSplit (go1.Width, go1.Slot.Width, go2.Width, go2.Slot.Width);
-                               min1 = go1.MinimumSize.Width;
-                               min2 = go2.MinimumSize.Width;
-                               max1 = go1.MaximumSize.Width;
-                               max2 = go2.MaximumSize.Width;
-                               if (init1 >= 0)
-                                       go1.Width = init1;
-                               if (init2 >= 0)
-                                       go2.Width = init2;
-                       } else {
-                               initSplit (go1.Height, go1.Slot.Height, go2.Height, go2.Slot.Height);
-                               min1 = go1.MinimumSize.Height;
-                               min2 = go2.MinimumSize.Height;
-                               max1 = go1.MaximumSize.Height;
-                               max2 = go2.MaximumSize.Height;
-                               if (init1 >= 0)
-                                       go1.Height = init1;
-                               if (init2 >= 0)
-                                       go2.Height = init2;
-                       }
-               }
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseMove (sender, e);
-
-                       if (!IsActive || go1 == null || go2 == null)
-                               return;
-
-                       GenericStack gs = Parent as GenericStack;
-                       int newDelta = delta, size1 = init1 , size2 = init2;
-                       if (gs.Orientation == Orientation.Horizontal) {
-                               newDelta -= e.XDelta;
-                               if (size1 < 0)
-                                       size1 = go1.Slot.Width + delta;
-                               if (size2 < 0)
-                                       size2 = go2.Slot.Width - delta;
-                       } else {
-                               newDelta -= e.YDelta;
-                               if (size1 < 0)
-                                       size1 = go1.Slot.Height + delta;
-                               if (size2 < 0)
-                                       size2 = go2.Slot.Height - delta;
-                       }
-
-                       if (size1 - newDelta < min1 || (max1 > 0 && size1 - newDelta > max1) ||
-                               size2 + newDelta < min2 || (max2 > 0 && size2 + newDelta > max2))
-                               return;
-
-                       delta = newDelta;
-
-                       if (gs.Orientation == Orientation.Horizontal) {
-                               if (init1 >= 0)
-                                       go1.Width = init1 - delta;
-                               if (init2 >= 0)
-                                       go2.Width = init2 + delta;
-                       } else {
-                               if (init1 >= 0)
-                                       go1.Height = init1 - delta;
-                               if (init2 >= 0)
-                                       go2.Height = init2 + delta;
-                       }
-               }
-               public override void onMouseUp (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseUp (sender, e);
-
-                       GenericStack gs = Parent as GenericStack;
-
-                       if (init1 >= 0 && u1 == Unit.Percent) {
-                               if (gs.Orientation == Orientation.Horizontal)
-                                       go1.Width = new Measure ((int)Math.Ceiling (
-                                               go1.Width.Value * 100.0 / (double)gs.Slot.Width), Unit.Percent);
-                               else
-                                       go1.Height = new Measure ((int)Math.Ceiling (
-                                               go1.Height.Value * 100.0 / (double)gs.Slot.Height), Unit.Percent);
-                       }
-                       if (init2 >= 0 && u2 == Unit.Percent) {
-                               if (gs.Orientation == Orientation.Horizontal)
-                                       go2.Width = new Measure ((int)Math.Floor (
-                                               go2.Width.Value * 100.0 / (double)gs.Slot.Width), Unit.Percent);
-                               else
-                                       go2.Height = new Measure ((int)Math.Floor (
-                                               go2.Height.Value * 100.0 / (double)gs.Slot.Height), Unit.Percent);
-                       }
-               }
-               public override bool UpdateLayout (LayoutingType layoutType)
-               {
-                       GenericStack gs = Parent as GenericStack;
-                       if (layoutType == LayoutingType.Width){
-                               if (gs.Orientation == Orientation.Horizontal)
-                                       Width = thickness;
-                               else
-                                       Width = Measure.Stretched;
-                       } else if (layoutType == LayoutingType.Height){
-                               if (gs.Orientation == Orientation.Vertical)
-                                       Height = thickness;
-                               else
-                                       Height = Measure.Stretched;
-                       }
-                       return base.UpdateLayout (layoutType);
-               }
-               public override bool PointIsIn (ref Point m)
-               {
-                       if (!(Visible & IsEnabled)||IsDragged)
-                               return false;
-                       if (!Parent.PointIsIn(ref m))
-                               return false;
-                       m -= (Parent.getSlot().Position + Parent.ClientRectangle.Position) ;
-                       Rectangle r = Slot;
-                       if (Width == Measure.Stretched)
-                               r.Inflate (0, 5);
-                       else
-                               r.Inflate (5, 0);
-                       return r.ContainsOrIsEqual (m); 
-               }
-               #endregion
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/TabItem.cs b/Crow/src/GraphicObjects/TabItem.cs
deleted file mode 100644 (file)
index 7c20a33..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-//
-// TabItem.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.Xml.Serialization;
-using System.ComponentModel;
-using System.Diagnostics;
-using Crow.Cairo;
-using System.Linq;
-
-namespace Crow
-{
-       public class TabItem : TemplatedContainer
-       {
-               #region CTOR
-               protected TabItem() : base(){}
-               public TabItem (Interface iface) : base(iface){}
-               #endregion
-
-               public event EventHandler QueryClose;
-
-               internal TabView tview = null;
-
-               #region Private fields
-               Widget titleWidget;
-               int tabOffset;
-               bool isSelected;
-               //Measure tabThickness;
-               Fill selectedBackground = Color.Transparent;
-               #endregion
-
-               #region TemplatedControl overrides
-               public override Widget Content {
-                       get {
-                               return _contentContainer == null ? null : _contentContainer.Child;
-                       }
-                       set {
-                               if (Content != null) {
-                                       Content.LogicalParent = null;
-                                       _contentContainer.SetChild (null);
-                               }
-                               _contentContainer.SetChild(value);
-                               if (value != null)
-                                       value.LogicalParent = this;
-                       }
-               }
-               protected override void loadTemplate(Widget template = null)
-               {
-                       base.loadTemplate (template);
-
-                       titleWidget = this.child.FindByName ("TabTitle");
-               }
-               internal Widget TabTitle { get { return titleWidget; }}
-               #endregion
-
-               /// <summary>
-               /// order of redrawing, items can't be reordered in TemplatedGroup due to data linked, so we need another index
-               /// instead of children list order
-               /// </summary>
-               public int viewIndex = 0;
-               public virtual int ViewIndex {
-                       get { return viewIndex; }
-                       set {
-                               if (viewIndex == value)
-                                       return;
-                               viewIndex = value;
-                               NotifyValueChanged ("ViewIndex", viewIndex);
-                       }
-               }
-                       
-               [DefaultValue(0)]
-               public int TabOffset {
-                       get { return tabOffset; }
-                       set {
-                               if (tabOffset == value)
-                                       return;
-                               tabOffset = value;
-                               NotifyValueChanged ("TabOffset", tabOffset);
-
-                               RegisterForLayouting (LayoutingType.X);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               public Measure TabHeight {
-                       get { return tview == null ? Measure.Fit : tview.TabHeight; }
-               }
-               public Measure TabWidth {
-                       get { return tview == null ? Measure.Fit : tview.TabWidth; }
-               }
-               [DefaultValue(false)]
-               public virtual bool IsSelected {
-                       get { return isSelected; }
-                       set {
-                               if (isSelected == value)
-                                       return;
-
-                               if (tview != null)
-                                       tview.SelectedTab = tview.Children.IndexOf(this);
-                               
-                               isSelected = value;
-                               NotifyValueChanged ("IsSelected", isSelected);
-                               RegisterForRedraw ();
-                       }
-               }
-
-               /// <summary>
-               /// background fill of the control, maybe solid color, gradient, image, or svg
-               /// </summary>
-               [DesignCategory ("Appearance")][DefaultValue("DimGrey")]
-               public virtual Fill SelectedBackground {
-                       get { return selectedBackground; }
-                       set {
-                               if (selectedBackground == value)
-                                       return;                         
-                               if (value == null)
-                                       return;
-                               selectedBackground = value;
-                               NotifyValueChanged ("SelectedBackground", selectedBackground);
-                               RegisterForRedraw ();
-                       }
-               }
-               protected override void onDraw (Context gr)
-               {
-                       gr.Save ();
-
-                       TabView tv = Parent as TabView;
-
-                       Rectangle r = TabTitle.Slot;
-                       r.Width = TabWidth;
-
-                       gr.MoveTo (0.5, r.Bottom-0.5);
-                       gr.LineTo (r.Left - tv.LeftSlope, r.Bottom-0.5);
-                       gr.CurveTo (
-                               r.Left - tv.LeftSlope / 2, r.Bottom-0.5,
-                               r.Left - tv.LeftSlope / 2, 0.5,
-                               r.Left, 0.5);
-                       gr.LineTo (r.Right, 0.5);
-                       gr.CurveTo (
-                               r.Right + tv.RightSlope / 2, 0.5,
-                               r.Right + tv.RightSlope / 2, r.Bottom-0.5,
-                               r.Right + tv.RightSlope, r.Bottom-0.5);
-                       gr.LineTo (Slot.Width-0.5, r.Bottom-0.5);
-
-
-                       gr.LineTo (Slot.Width-0.5, Slot.Height-0.5);
-                       gr.LineTo (0.5, Slot.Height-0.5);
-                       gr.ClosePath ();
-                       gr.LineWidth = 1;
-                       Foreground.SetAsSource (gr);
-                       gr.StrokePreserve ();
-                       gr.ClipPreserve ();
-
-                       if (IsSelected)
-                               SelectedBackground.SetAsSource (gr, ClientRectangle);
-                       else
-                               Background.SetAsSource (gr, ClientRectangle);
-
-                       gr.Fill ();
-
-                       base.onDraw (gr);
-
-                       gr.Restore ();
-               }
-
-               Point dragStartPoint;
-               int dragThreshold = 16;
-               int dis = 128;
-               internal TabView savedParent = null;
-
-
-               void makeFloating (TabView tv) {                        
-                       lock (IFace.UpdateMutex) {                              
-                               ImageSurface di = new ImageSurface (Format.Argb32, dis, dis);
-                               IFace.DragImageHeight = dis;
-                               IFace.DragImageWidth = dis;
-                               using (Context ctx = new Context (di)) {
-                                       double div = Math.Max (LastPaintedSlot.Width, LastPaintedSlot.Height);
-                                       double s = (double)dis / div;
-                                       ctx.Scale (s, s);
-                                       if (bmp == null)
-                                               this.onDraw (ctx);
-                                       else {
-                                               if (LastPaintedSlot.Width>LastPaintedSlot.Height)
-                                                       ctx.SetSourceSurface (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2);
-                                               else
-                                                       ctx.SetSourceSurface (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0);
-
-                                               ctx.Paint ();
-                                       }
-                               }
-                               IFace.DragImage = di;
-                       }
-                       tv.RemoveChild (this);
-                       savedParent = tv;
-               }
-
-               public override ILayoutable Parent {
-                       get {
-                               return base.Parent;
-                       }
-                       set {
-                               base.Parent = value;
-                               if (value != null) {
-                                       dragStartPoint = IFace.Mouse.Position;
-                                       savedParent = value as TabView;
-                               }
-                       }
-               }
-               protected override void onStartDrag (object sender, DragDropEventArgs e)
-               {
-                       base.onStartDrag (sender, e);
-
-                       dragStartPoint = IFace.Mouse.Position;
-               }
-               protected override void onEndDrag (object sender, DragDropEventArgs e)
-               {
-                       base.onEndDrag (sender, e);
-
-                       if (Parent != null)
-                               return;
-
-                       savedParent.AddChild (this);
-
-                       IFace.ClearDragImage ();
-               }
-               protected override void onDrop (object sender, DragDropEventArgs e)
-               {
-                       base.onDrop (sender, e);
-                       if (Parent != null)
-                               return;
-                       TabView tv = e.DropTarget as TabView;
-                       if (tv == null)
-                               return;
-
-                       IFace.ClearDragImage ();
-
-                       tv.AddChild (this);
-               }
-               #region Mouse Handling
-               public override bool PointIsIn (ref Point m)
-               {
-                       if (!base.PointIsIn (ref m))
-                               return false;
-                       if (tview == null)//double check this, just added to prevent exception
-                               return false;
-                       if (m.Y < tview.TabHeight)
-                               return TabTitle.Slot.ContainsOrIsEqual (m);
-                       else
-                               return this.isSelected;
-               }
-               public override void onMouseUp (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseUp (sender, e);
-                       tview?.UpdateLayout (LayoutingType.ArrangeChildren);
-               }
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseMove (sender, e);
-
-                       if (Parent == null)
-                               return;
-                       
-                       if (!IsDragged)
-                               return;
-
-                       TabView tv = Parent as TabView;
-                       if (Math.Abs (e.Position.Y - dragStartPoint.Y) > dragThreshold ||
-                               Math.Abs (e.Position.X - dragStartPoint.X) > dragThreshold) {
-                               makeFloating (tv);
-                               return;
-                       }
-
-                       Rectangle cb = ClientRectangle;
-
-                       int tmp = TabOffset + e.XDelta;
-                       if (tmp < tview.LeftSlope) {                            
-                               TabOffset = tview.LeftSlope;
-                       } else if (tmp > cb.Width - tv.RightSlope - tv.TabWidth) {
-                               TabOffset = cb.Width - tv.RightSlope - tv.TabWidth;
-                       }else{
-                               dragStartPoint.X = e.Position.X;
-                               TabItem[] tabItms = tv.Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
-                               if (ViewIndex > 0 && e.XDelta < 0) {
-                                       TabItem previous = tabItms [ViewIndex - 1];
-                                       if (tmp < previous.TabOffset + tview.TabWidth / 2) {
-                                               previous.ViewIndex = ViewIndex;
-                                               ViewIndex--;
-                                               tv.UpdateLayout (LayoutingType.ArrangeChildren);
-                                       }
-
-                               }else if (ViewIndex < tabItms.Length - 1 && e.XDelta > 0) {
-                                       TabItem next = tabItms [ViewIndex + 1];
-                                       if (tmp > next.TabOffset - tview.TabWidth / 2){
-                                               next.ViewIndex = ViewIndex;
-                                               ViewIndex++;
-                                               tv.UpdateLayout (LayoutingType.ArrangeChildren);
-                                       }
-                               }
-                               TabOffset = tmp;
-                       }
-               }
-               public void butCloseTabClick (object sender, MouseButtonEventArgs e){                   
-                       QueryClose.Raise (this, null);
-                       //if tab is used as a templated item root in a templatedGroup, local datasource
-                       //is not null, in this case, removing the data entries will delete automatically the item
-                       if (localDataSourceIsNull)
-                               (Parent as TabView)?.DeleteChild (this);
-               }
-               #endregion
-
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/TabView.cs b/Crow/src/GraphicObjects/TabView.cs
deleted file mode 100644 (file)
index 423b8ab..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-//
-// TabView.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.Xml.Serialization;
-using System.ComponentModel;
-using Crow.Cairo;
-using System.Diagnostics;
-using System.Linq;
-
-namespace Crow
-{      
-       public class TabView : Group
-       {
-               #region CTOR
-               public TabView() : base(){}
-               public TabView (Interface iface) : base(iface){}
-               #endregion
-
-               #region Private fields
-               int adjustedTab = -1;
-               int leftSlope;
-               int rightSlope;
-               Measure tabHeight, tabWidth;
-               Orientation _orientation;
-               int selectedTab;
-               #endregion
-
-               #region public properties
-               [DefaultValue(Orientation.Horizontal)]
-               public virtual Orientation Orientation
-               {
-                       get { return _orientation; }
-                       set {
-                               if (_orientation == value)
-                                       return;
-                               _orientation = value;
-                               NotifyValueChanged ("Orientation", _orientation);
-                               if (_orientation == Orientation.Horizontal)
-                                       NotifyValueChanged ("TabOrientation", Orientation.Vertical);
-                               else
-                                       NotifyValueChanged ("TabOrientation", Orientation.Horizontal);                          
-                               this.RegisterForLayouting (LayoutingType.ArrangeChildren);
-                       }
-               }
-               [DefaultValue(16)]
-               public int LeftSlope
-               {
-                       get { return leftSlope; }
-                       set {
-                               if (leftSlope == value)
-                                       return;
-                               leftSlope = value;
-                               NotifyValueChanged ("leftSlope", leftSlope);
-                               //tabSizeHasChanged = true;
-                               //RegisterForLayouting (LayoutingType.ArrangeChildren);
-                       }
-               }
-               //bool tabSizeHasChanged = false;
-               [DefaultValue(16)]
-               public int RightSlope
-               {
-                       get { return rightSlope; }
-                       set {
-                               if (rightSlope == value)
-                                       return;
-                               rightSlope = value;
-                               NotifyValueChanged ("RightSlope", rightSlope);
-                               //tabSizeHasChanged = true;
-                               //RegisterForLayouting (LayoutingType.ArrangeChildren);
-                       }
-               }
-               [DefaultValue("18")]
-               public Measure TabHeight {
-                       get { return tabHeight; }
-                       set {
-                               if (tabHeight == value)
-                                       return;
-                               tabHeight = value;
-                               NotifyValueChanged ("TabHeight", tabHeight);
-//                             childrenRWLock.EnterReadLock ();
-//                             foreach (GraphicObject ti in Children) {
-//                                     ti.NotifyValueChanged ("TabHeight", tabHeight);
-//                             }
-//                             childrenRWLock.ExitReadLock ();
-                               RegisterForLayouting (LayoutingType.ArrangeChildren);
-                       }
-               }
-               [DefaultValue("120")]
-               public Measure TabWidth {
-                       get { return adjustedTab > 0 ? (Measure)adjustedTab : tabWidth; }
-                       set {
-                               if (tabWidth == value)
-                                       return;
-                               tabWidth = value;
-                               NotifyValueChanged ("TabWidth", TabWidth);
-//
-//                             childrenRWLock.EnterReadLock ();
-//                             foreach (GraphicObject ti in Children) { 
-//                                     ti.NotifyValueChanged ("TabWidth", tabWidth);
-//                             }
-//                             childrenRWLock.ExitReadLock ();
-                               RegisterForLayouting (LayoutingType.ArrangeChildren);
-                       }
-               }
-
-               public virtual int SelectedTab {
-                       get { return selectedTab; }
-                       set {
-                               if (value == selectedTab)
-                                       return;
-
-                               if (selectedTab < Children.Count && selectedTab >= 0)
-                                       (Children [selectedTab] as TabItem).IsSelected = false;
-
-                               selectedTab = value;
-
-                               if (selectedTab < Children.Count && selectedTab >= 0)
-                                       (Children [selectedTab] as TabItem).IsSelected = true;
-
-                               NotifyValueChanged ("SelectedTab", selectedTab);
-                               RegisterForRedraw ();
-                       }
-               }
-               #endregion
-
-               public override void AddChild (Widget child)
-               {
-                       TabItem ti = child as TabItem;
-                       if (ti == null)
-                               throw new Exception ("TabView control accept only TabItem as child.");
-
-                       ti.MouseDown += Ti_MouseDown;
-                       ti.TabTitle.LayoutChanged += Ti_TabTitle_LayoutChanged;
-                       ti.tview = this;
-
-                       base.AddChild (child);
-
-                       SelectedTab = ti.ViewIndex = Children.Count - 1;
-                       this.RegisterForLayouting (LayoutingType.ArrangeChildren);
-               }
-               public override void RemoveChild (Widget child)
-               {
-                       TabItem ti = child as TabItem;
-                       if (ti == null)
-                               throw new Exception ("TabView control accept only TabItem as child.");
-
-                       ti.MouseDown -= Ti_MouseDown;
-                       ti.TabTitle.LayoutChanged -= Ti_TabTitle_LayoutChanged;
-                       ti.tview = null;
-
-                       childrenRWLock.EnterReadLock ();
-
-                       TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
-                       int selTabViewIdx = -1;
-
-                       if (SelectedTab < tabItms.Length && SelectedTab >= 0)
-                               selTabViewIdx = (Children [SelectedTab] as TabItem).ViewIndex;
-
-                       for (int i = selTabViewIdx+1; i < tabItms.Length; i++)
-                               tabItms [i].ViewIndex--;
-
-                       if (selTabViewIdx > tabItms.Length - 2)
-                               selTabViewIdx = tabItms.Length - 2;
-
-                       if (selTabViewIdx < 0)
-                               SelectedTab = -1;
-                       else
-                               SelectedTab = Children.IndexOf (tabItms [selTabViewIdx]);
-
-                       childrenRWLock.ExitReadLock ();
-
-                       base.RemoveChild (child);
-               }
-
-               public override bool ArrangeChildren { get { return true; } }
-               public override bool UpdateLayout (LayoutingType layoutType)
-               {
-                       RegisteredLayoutings &= (~layoutType);
-
-                       if (layoutType == LayoutingType.ArrangeChildren && Children.Count > 0) {
-                               Rectangle cb = ClientRectangle;
-
-                               int tabSpace = tabWidth + leftSlope;
-                               int tc = Children.Count (c => c.Visible == true);
-
-                               if (tc > 0)
-                                       tabSpace = Math.Min(tabSpace, (cb.Width-rightSlope) / tc);
-
-                               if (tabSpace < tabWidth + leftSlope)
-                                       adjustedTab = tabSpace - leftSlope;
-                               else
-                                       adjustedTab = -1;
-
-                               //Console.WriteLine ("tabspace: {0} tw:{1}", tabSpace, tabWidth);
-
-                               childrenRWLock.EnterReadLock();
-                               TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
-                               childrenRWLock.ExitReadLock();
-                               int curOffset = leftSlope;
-
-                               for (int i = 0; i < tabItms.Length; i++) {
-                                       if (!tabItms [i].Visible)
-                                               continue;
-                                       tabItms [i].NotifyValueChanged ("TabHeight", tabHeight);
-                                       tabItms [i].NotifyValueChanged ("TabWidth", TabWidth);
-                                       if (!tabItms [i].IsDragged) {
-                                               tabItms [i].TabOffset = curOffset;
-                                               //Console.WriteLine ("offset: {0}=>{1}", tabItms [i].Name, tabItms [i].TabOffset);
-                                       }
-                                       if (Orientation == Orientation.Horizontal) {
-                                               curOffset += tabSpace;
-                                       } else
-                                               curOffset += tabSpace;                                  
-                               }
-
-                               //if no layouting remains in queue for item, registre for redraw
-                               if (RegisteredLayoutings == LayoutingType.None && IsDirty)
-                                       IFace.EnqueueForRepaint (this);
-
-                               return true;
-                       }
-
-                       return base.UpdateLayout(layoutType);
-               }
-               public override void OnLayoutChanges (LayoutingType layoutType)
-               {
-                       if (_orientation == Orientation.Horizontal) {
-                               if (layoutType == LayoutingType.Width)
-                                       RegisterForLayouting (LayoutingType.ArrangeChildren);                           
-                       } else if (layoutType == LayoutingType.Height)
-                               RegisterForLayouting (LayoutingType.ArrangeChildren);                   
-                       
-                       base.OnLayoutChanges (layoutType);
-               }
-
-               protected override void onDraw (Context gr)
-               {
-                       Rectangle rBack = new Rectangle (Slot.Size);
-
-                       Background.SetAsSource (gr, rBack);
-                       CairoHelpers.CairoRectangle(gr,rBack, CornerRadius);
-                       gr.Fill ();
-
-                       gr.Save ();
-
-                       if (ClipToClientRect) {
-                               //clip to client zone
-                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
-                               gr.Clip ();
-                       }
-
-                       childrenRWLock.EnterReadLock ();
-
-                       TabItem[] tabItms = Children.Where(tt=>tt.Visible).Cast<TabItem> ().
-                               OrderBy (t => t.ViewIndex).ToArray ();
-
-                       int selTabViewIdx = -1;
-                       if (SelectedTab < tabItms.Length && SelectedTab >= 0)
-                               selTabViewIdx = (Children [SelectedTab] as TabItem).ViewIndex;
-
-                       childrenRWLock.ExitReadLock ();
-
-                       int i = 0;
-                       while (i < selTabViewIdx) {
-                               tabItms [i].Paint (ref gr);
-                               i++;
-                       }
-                       i = tabItms.Length - 1;
-                       while (i > selTabViewIdx) {
-                               tabItms [i].Paint (ref gr);
-                               i--;
-                       }
-
-                       if (selTabViewIdx >= 0)
-                               tabItms [selTabViewIdx].Paint (ref gr);
-               
-                       gr.Restore ();
-               }
-
-               protected override void onDragEnter (object sender, DragDropEventArgs e)
-               {
-                       base.onDragEnter (sender, e);
-
-                       TabItem ti = e.DragSource as TabItem;
-                       if (ti == null)
-                               return;
-                       if (ti.Parent != null || ti.savedParent == this)
-                               return;
-
-                       this.AddChild (ti);
-
-                       Point p = ScreenPointToLocal (IFace.Mouse.Position) - Margin;
-
-                       p.X = Math.Max (leftSlope, p.X);
-                       p.X = Math.Min (ClientRectangle.Width - rightSlope - TabWidth, p.X);
-                       ti.TabOffset = p.X;
-
-                       IFace.ClearDragImage ();
-
-               }
-
-               void Ti_TabTitle_LayoutChanged (object sender, LayoutingEventArgs e)
-               {
-                       if (e.LayoutType == LayoutingType.X)                            
-                               RegisterForLayouting (LayoutingType.ArrangeChildren);                   
-               }
-               void Ti_MouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       SelectedTab = Children.IndexOf (sender as Widget);
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/TemplatedContainer.cs b/Crow/src/GraphicObjects/TemplatedContainer.cs
deleted file mode 100644 (file)
index 0acd876..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.Xml.Serialization;
-using System.Xml;
-using System.Reflection;
-
-namespace Crow
-{
-       /// <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
-       {
-               #if DESIGN_MODE
-               public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem)
-               {
-                       if (this.design_isTGItem)
-                               return;
-                       base.getIML (doc, parentElem);
-                       if (!HasContent)
-                               return;
-                       Content.getIML (doc, parentElem.LastChild);
-               }
-               #endif
-
-               #region CTOR
-               protected TemplatedContainer() : base(){}
-               public TemplatedContainer (Interface iface) : base(iface){}
-               #endregion
-
-               protected Container _contentContainer;
-
-               /// <summary>
-               /// Single child of this templated container.
-               /// </summary>
-               public virtual Widget 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(Widget template = null)
-               {
-                       base.loadTemplate (template);
-                       _contentContainer = this.child.FindByName ("Content") as Container;
-               }
-
-               #region GraphicObject overrides
-               public override Widget FindByName (string nameToFind)
-               {
-                       if (Name == nameToFind)
-                               return this;
-
-                       return Content == null ? null : Content.FindByName (nameToFind);
-               }
-               public override bool Contains (Widget goToFind)
-               {
-                       if (Content == goToFind)
-                               return true;
-                       if (Content?.Contains (goToFind) == true)
-                               return true;
-                       return base.Contains (goToFind);
-               }
-               #endregion
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/TemplatedControl.cs b/Crow/src/GraphicObjects/TemplatedControl.cs
deleted file mode 100644 (file)
index 563fc0a..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.ComponentModel;
-using System.IO;
-using System.Reflection;
-using System.Xml;
-using Crow.Cairo;
-
-namespace Crow
-{
-       /// <summary>
-       /// Base class for all templated widget
-       /// </summary>
-       public abstract class TemplatedControl : PrivateContainer
-       {
-               #if DESIGN_MODE
-               public bool design_inlineTemplate = false;
-               public override void getIML (XmlDocument doc, XmlNode parentElem)
-               {
-                       if (this.design_isTGItem)
-                               return;
-                       base.getIML (doc, parentElem);
-                       if (child == null || !design_inlineTemplate)
-                               return;
-                       XmlElement xe = doc.CreateElement("Template");
-                       child.getIML (doc, xe);
-                       parentElem.LastChild.AppendChild (xe);
-               }
-               #endif
-
-               #region CTOR
-               protected TemplatedControl() : base(){}
-               public TemplatedControl (Interface iface) : base(iface){}
-               #endregion
-
-               string _template;
-               string caption;
-
-               /// <summary>
-               /// Template path
-               /// </summary>
-               //TODO: this property should be renamed 'TemplatePath'
-               [DefaultValue(null)]
-               public string Template {
-                       get { return _template; }
-                       set {
-                               if (_template == value)
-                                       return;
-                               _template = value;
-
-                               if (string.IsNullOrEmpty(_template))
-                                       loadTemplate ();
-                               else
-                                       loadTemplate (IFace.CreateTemplateInstance (_template, this.GetType()));
-                       }
-               }
-               /// <summary>
-               /// a caption being recurrent need in templated widget, it is declared here.
-               /// </summary>
-               [DefaultValue("Templated Control")]
-               public virtual string Caption {
-                       get { return caption; }
-                       set {
-                               if (caption == value)
-                                       return;
-                               caption = value;
-                               NotifyValueChanged ("Caption", caption);
-                       }
-               }
-
-               #region GraphicObject overrides
-
-               public override void Initialize ()
-               {
-                       loadTemplate ();
-                       base.Initialize ();
-               }
-               /// <summary>
-               /// override search method from GraphicObject to prevent
-               /// searching inside template
-               /// </summary>
-               /// <returns>widget identified by name, or null if not found</returns>
-               /// <param name="nameToFind">widget's name to find</param>
-               public override Widget FindByName (string nameToFind) => nameToFind == this.Name ? this : null;
-
-               /// <summary>
-               ///onDraw is overrided to prevent default drawing of background, template top container
-               ///may have a binding to root background or a fixed one.
-               ///this allow applying root background to random template's component
-               /// </summary>
-               /// <param name="gr">Backend context</param>
-               protected override void onDraw (Context gr)
-               {
-                       gr.Save ();
-
-                       if (ClipToClientRect) {
-                               //clip to client zone
-                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
-                               gr.Clip ();
-                       }
-
-                       if (child != null)
-                               child.Paint (ref gr);
-                       gr.Restore ();
-               }
-               #endregion
-
-               /// <summary>
-               /// Loads the template. Each TemplatedControl MUST provide a default template
-               /// It must be an embedded ressource with ID = fullTypeName.template
-               /// Entry assembly is search first, then the one where the type is defined
-               /// </summary>
-               /// <param name="template">Optional template instance</param>
-               protected virtual void loadTemplate(Widget template = null)
-               {
-                       if (this.child != null)//template change, bindings has to be reset
-                               this.ClearTemplateBinding();
-                       
-                       if (template == null) {
-                               int mdTok = this.GetType ().MetadataToken;
-
-                               if (!IFace.DefaultTemplates.ContainsKey (mdTok)) {
-                                       string defTmpId = this.GetType ().FullName + ".template";
-                                       Stream s = Assembly.GetEntryAssembly ().GetManifestResourceStream (defTmpId);
-                                       if (s == null)
-                                               s = Assembly.GetAssembly (this.GetType ()).GetManifestResourceStream (defTmpId);
-                                       if (s == null)
-                                               throw new Exception (string.Format ("No default template found for '{0}'", this.GetType ().FullName));
-                                       IFace.DefaultTemplates [mdTok] = new IML.Instantiator (IFace, s, defTmpId);
-                               }
-                               this.SetChild (IFace.DefaultTemplates[mdTok].CreateInstance());
-                       }else
-                               this.SetChild (template);
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/TemplatedGroup.cs b/Crow/src/GraphicObjects/TemplatedGroup.cs
deleted file mode 100644 (file)
index da87b91..0000000
+++ /dev/null
@@ -1,530 +0,0 @@
-//
-// TemplatedGroup.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.Collections;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using System.Threading;
-using Crow.IML;
-
-namespace Crow {
-       public abstract class TemplatedGroup : TemplatedControl
-       {
-               #if DESIGN_MODE
-               public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem)
-               {
-                       if (this.design_isTGItem)
-                               return;
-                       base.getIML (doc, parentElem);
-
-                       if (string.IsNullOrEmpty(_itemTemplate)) {
-                               foreach (ItemTemplate it in ItemTemplates.Values) 
-                                       it.getIML (doc, parentElem.LastChild);                          
-                       }
-
-                       foreach (Widget g in Items) {
-                               g.getIML (doc, parentElem.LastChild);   
-                       }
-               }
-               #endif
-
-               #region CTOR
-               protected TemplatedGroup() : base(){}
-               public TemplatedGroup (Interface iface) : base(iface){}
-               #endregion
-
-               protected Group items;
-               string _itemTemplate, dataTest;
-
-               #region events
-               public event EventHandler<SelectionChangeEventArgs> SelectedItemChanged;
-               public event EventHandler Loaded;
-               #endregion
-
-               IEnumerable data;
-               int _selectedIndex = -1;
-               Color selBackground, selForeground;
-
-               int itemPerPage = 50;
-               CrowThread loadingThread = null;
-
-               bool isPaged = false;
-
-               #region Templating
-               //TODO: dont instantiate ItemTemplates if not used
-               //but then i should test if null in msil gen
-               public Dictionary<string, ItemTemplate> ItemTemplates = new Dictionary<string, ItemTemplate>();
-
-               /// <summary>
-               /// Keep track of expanded subnodes and closed time to unload
-               /// </summary>
-               //Dictionary<GraphicObject, Stopwatch> nodes = new Dictionary<GraphicObject, Stopwatch>();
-               internal List<Widget> nodes = new List<Widget>();
-               /// <summary>
-               /// 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>          
-               public string ItemTemplate {
-                       get { return _itemTemplate; }
-                       set {
-                               if (value == _itemTemplate)
-                                       return;
-
-                               _itemTemplate = value;
-
-                               //TODO:reload list with new template?
-                               NotifyValueChanged("ItemTemplate", _itemTemplate);
-                       }
-               }
-               protected override void loadTemplate(Widget template = null)
-               {
-                       base.loadTemplate (template);
-
-                       items = this.child.FindByName ("ItemsContainer") as Group;
-                       if (items == null)
-                               throw new Exception ("TemplatedGroup template Must contain a Group named 'ItemsContainer'");
-                       if (items.Children.Count == 0)
-                               NotifyValueChanged ("HasChildren", false);
-                       else
-                               NotifyValueChanged ("HasChildren", true);
-               }
-               /// <summary>
-               /// Use to define condition on Data item for selecting among ItemTemplates.
-               /// Default value is 'TypeOf' for selecting Template depending on Type of Data.
-               /// Other possible values are properties of Data
-               /// </summary>
-               /// <value>The data property test.</value>
-               [DefaultValue("TypeOf")]
-               public string DataTest {
-                       get { return dataTest; }
-                       set {
-                               if (value == dataTest)
-                                       return;
-
-                               dataTest = value;
-
-                               NotifyValueChanged("DataTest", dataTest);
-                       }
-               }
-               #endregion
-
-               public virtual List<Widget> Items{
-                       get {
-                               return isPaged ? items.Children.SelectMany(x => (x as Group).Children).ToList()
-                               : items.Children;
-                       }
-               }
-               [DefaultValue(-1)]public virtual int SelectedIndex{
-                       get { return _selectedIndex; }
-                       set {
-                               if (value == _selectedIndex)
-                                       return;
-
-                               /*if (_selectedIndex >= 0 && Items.Count > _selectedIndex) {
-                                       Items[_selectedIndex].Foreground = Color.Transparent;
-                                       Items[_selectedIndex].Background = Color.Transparent;
-                               }*/
-
-                               _selectedIndex = value;
-
-                               /*if (_selectedIndex >= 0 && Items.Count > _selectedIndex) {
-                                       Items[_selectedIndex].Foreground = SelectionForeground;
-                                       Items[_selectedIndex].Background = SelectionBackground;
-                               }*/
-
-                               NotifyValueChanged ("SelectedIndex", _selectedIndex);
-                               NotifyValueChanged ("SelectedItem", SelectedItem);
-                               SelectedItemChanged.Raise (this, new SelectionChangeEventArgs (SelectedItem));
-                       }
-               }
-               [XmlIgnore]public virtual object SelectedItem{
-                       get { return data == null ? null : _selectedIndex < 0 ? data.GetDefaultValue() : ((IList)data)?[_selectedIndex]; }
-                       set {
-                               if (data == null) {
-                                       SelectedIndex = -1;
-                                       return;
-                               }
-                               //TODO:double check if value type will be notified to binding sys
-                               if (value == SelectedItem)
-                                       return;
-                               
-                               SelectedIndex = (int)((IList)data)?.IndexOf (value);
-                       }
-               }
-               [XmlIgnore]public bool HasItems {
-                       get { return Items.Count > 0; }
-               }
-               public IEnumerable Data {
-                       get { return data; }
-                       set {
-                               if (value == data)
-                                       return;
-
-                               cancelLoadingThread ();
-
-                               if (data is IObservableList) {
-                                       IObservableList ol = data as IObservableList;
-                                       ol.ListAdd -= Ol_ListAdd;
-                                       ol.ListRemove -= Ol_ListRemove;
-                               }
-
-                               data = value;
-
-                               if (data is IObservableList) {
-                                       IObservableList ol = data as IObservableList;
-                                       ol.ListAdd += Ol_ListAdd;
-                                       ol.ListRemove += Ol_ListRemove;
-                               }
-
-                               NotifyValueChanged ("Data", data);
-
-                               lock (IFace.UpdateMutex)
-                                       ClearItems ();
-
-                               if (data == null)
-                                       return;
-
-                               loadingThread = new CrowThread (this, loading);
-                               loadingThread.Finished += (object sender, EventArgs e) => (sender as TemplatedGroup).Loaded.Raise (sender, e);
-                               loadingThread.Start ();
-
-                               NotifyValueChanged ("SelectedIndex", _selectedIndex);
-                               NotifyValueChanged ("SelectedItem", SelectedItem);
-                               SelectedItemChanged.Raise (this, new SelectionChangeEventArgs (SelectedItem));
-                               NotifyValueChanged ("HasItems", HasItems);
-                       }
-               }
-
-               void Ol_ListRemove (object sender, ListChangedEventArg e)
-               {
-                       if (this.isPaged) {
-                               int p = e.Index / itemPerPage;
-                               int i = e.Index % itemPerPage;
-                               (items.Children [p] as Group).DeleteChild (i);
-                       } else
-                               items.DeleteChild (e.Index);
-               }
-
-               void Ol_ListAdd (object sender, ListChangedEventArg e)
-               {
-                       if (this.isPaged) {
-                               throw new NotImplementedException();
-//                             int p = e.Index / itemPerPage;
-//                             int i = e.Index % itemPerPage;
-//                             (items.Children [p] as Group).InsertChild (i, e.Element);
-                       } else
-                               loadItem (e.Element, items, dataTest);
-               }
-
-               [DefaultValue("SteelBlue")]
-               public virtual Color SelectionBackground {
-                       get { return selBackground; }
-                       set {
-                               if (value == selBackground)
-                                       return;
-                               selBackground = value;
-                               NotifyValueChanged ("SelectionBackground", selBackground);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue("White")]
-               public virtual Color SelectionForeground {
-                       get { return selForeground; }
-                       set {
-                               if (value == selForeground)
-                                       return;
-                               selForeground = value;
-                               NotifyValueChanged ("SelectionForeground", selForeground);
-                               RegisterForRedraw ();
-                       }
-               }
-
-               protected void raiseSelectedItemChanged(){
-                       SelectedItemChanged.Raise (this, new SelectionChangeEventArgs (SelectedItem));
-               }
-
-
-               public virtual void AddItem(Widget g){
-                       items.AddChild (g);
-                       g.LogicalParent = this;
-                       NotifyValueChanged ("HasChildren", true);
-               }
-               public virtual void RemoveItem(Widget g)
-               {
-                       g.LogicalParent = null;
-                       items.DeleteChild (g);
-                       if (items.Children.Count == 0)
-                               NotifyValueChanged ("HasChildren", false);
-               }
-
-               public virtual void ClearItems()
-               {
-                       _selectedIndex = -1;
-                       NotifyValueChanged ("SelectedIndex", _selectedIndex);
-                       NotifyValueChanged ("SelectedItem", null);
-
-                       items.ClearChildren ();
-                       NotifyValueChanged ("HasChildren", false);
-               }
-
-
-               #region GraphicObject overrides
-               public override Widget FindByName (string nameToFind)
-               {
-                       if (Name == nameToFind)
-                               return this;
-
-                       foreach (Widget w in Items) {
-                               Widget r = w.FindByName (nameToFind);
-                               if (r != null)
-                                       return r;
-                       }
-                       return null;
-               }
-               public override bool Contains (Widget goToFind)
-               {
-                       foreach (Widget w in Items) {
-                               if (w == goToFind)
-                                       return true;
-                               if (w.Contains (goToFind))
-                                       return true;
-                       }
-                       return base.Contains(goToFind);
-               }
-//             public override void ClearBinding ()
-//             {
-//                     if (items != null)
-//                             items.ClearBinding ();
-//
-//                     base.ClearBinding ();
-//             }
-//             public override void ResolveBindings ()
-//             {
-//                     base.ResolveBindings ();
-//                     if (items != null)
-//                             items.ResolveBindings ();
-//             }
-               #endregion
-
-               /// <summary>
-               /// Items loading thread
-               /// </summary>
-               void loading(){
-                       try {
-                               loadPage (data, items, dataTest);
-                       } catch {
-                               if (Monitor.IsEntered (IFace.LayoutMutex))
-                                       Monitor.Exit (IFace.LayoutMutex);
-                               Console.WriteLine ("loading thread aborted");
-                       }
-
-               }
-//                     //if (!ItemTemplates.ContainsKey ("default"))
-//                     //      ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
-//
-//                     for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) {
-//                             if ((bool)loadingThread?.cancelRequested) {
-//                                     this.Dispose ();
-//                                     return;
-//                             }
-//                             loadPage (i);
-//                             Thread.Sleep (1);
-//                     }
-//             }
-               void cancelLoadingThread(){
-                       if (loadingThread != null)
-                               loadingThread.Cancel ();
-               }
-               void loadPage(IEnumerable _data, Group page, string _dataTest)
-               {
-                       #if DEBUG_LOAD
-                       Stopwatch loadingTime = Stopwatch.StartNew ();
-                       #endif
-
-
-//                     if (typeof(TabView).IsAssignableFrom (items.GetType ())||
-//                             typeof(Menu).IsAssignableFrom (this.GetType())||
-//                             typeof(Wrapper).IsAssignableFrom (items.GetType ())) {
-                               //page = items;
-                               itemPerPage = int.MaxValue;
-                       //                      } else if (typeof(GenericStack).IsAssignableFrom (items.GetType ())) {
-                       //                              GenericStack gs = new GenericStack (items.CurrentInterface);
-                       //                              gs.Orientation = (items as GenericStack).Orientation;
-                       //                              gs.Width = items.Width;
-                       //                              gs.Height = items.Height;
-                       //                              gs.VerticalAlignment = items.VerticalAlignment;
-                       //                              gs.HorizontalAlignment = items.HorizontalAlignment;
-                       //                              page = gs;
-                       //                              page.Name = "page" + pageNum;
-                       //                              isPaged = true;
-                       //                      } else {
-                       //                              page = Activator.CreateInstance (items.GetType ()) as Group;
-                       //                              page.CurrentInterface = items.CurrentInterface;
-                       //                              page.Initialize ();
-                       //                              page.Name = "page" + pageNum;
-                       //                              isPaged = true;
-                       //                      }
-
-                       if (_data == null)
-                               return;
-
-                       foreach (object d in _data) {
-                               loadItem (d, page, _dataTest);
-                               if (loadingThread.cancelRequested)
-                                       break;
-                       }
-
-//                     if (page == items)
-//                             return;
-//                     lock (CurrentInterface.LayoutMutex)
-//                             items.AddChild (page);
-
-#if DEBUG_LOAD
-                       loadingTime.Stop ();
-                       using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
-                               sw.WriteLine ($"NEW ;{this.ToString(),-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
-                       }
-#endif
-               }
-
-               protected void loadItem(object o, Group page, string _dataTest){
-                       if (o == null)//TODO:surely a threading sync problem
-                               return;
-                       Widget g = null;
-                       ItemTemplate iTemp = null;
-                       Type dataType = o.GetType ();
-                       string itempKey = dataType.FullName;
-
-                       //if item template selection is not done depending on the type of item
-                       //dataTest must contains a member name of the item 
-                       if (_dataTest != "TypeOf") {
-                               try {
-                                       itempKey = CompilerServices.getValue (dataType, o, _dataTest)?.ToString ();
-                               } catch {
-                                       itempKey = dataType.FullName;
-                               }
-                       }
-
-                       if (ItemTemplates.ContainsKey (itempKey))
-                               iTemp = ItemTemplates [itempKey];
-                       else {
-                               foreach (string it in ItemTemplates.Keys) {
-                                       if (it == "default")
-                                               continue;
-                                       Type t = CompilerServices.getTypeFromName (it);
-                                       if (t == null)
-                                               continue;
-                                       if (t.IsAssignableFrom (dataType)) {//TODO:types could be cached
-                                               iTemp = ItemTemplates [it];
-                                               break;
-                                       }
-                               }
-                               if (iTemp == null)
-                                       iTemp = ItemTemplates ["default"];
-                       }
-
-                       Monitor.Enter (IFace.LayoutMutex);
-                               g = iTemp.CreateInstance();
-                               #if DESIGN_MODE
-                               g.design_isTGItem = true;
-                               #endif
-                               page.AddChild (g);
-//                             if (isPaged)
-                               g.LogicalParent = this;
-                               g.MouseClick += itemClick;
-                       Monitor.Exit (IFace.LayoutMutex);
-
-                       if (iTemp.Expand != null && g is Expandable) {
-                               Expandable e = g as Expandable;
-                               e.Expand += iTemp.Expand;
-                               if ((o as ICollection) == null)
-                                       e.GetIsExpandable = new BooleanTestOnInstance((instance) => true);
-                               else
-                                       e.GetIsExpandable = iTemp.HasSubItems;
-                       }
-
-                       g.DataSource = o;
-               }
-
-
-               //              protected void _list_LayoutChanged (object sender, LayoutingEventArgs e)
-               //              {
-               //                      #if DEBUG_LAYOUTING
-               //                      Debug.WriteLine("list_LayoutChanged");
-               //                      #endif
-               //                      if (_gsList.Orientation == Orientation.Horizontal) {
-               //                              if (e.LayoutType == LayoutingType.Width)
-               //                                      _gsList.Width = approxSize;
-               //                      } else if (e.LayoutType == LayoutingType.Height)
-               //                              _gsList.Height = approxSize;
-               //              }
-               int approxSize
-               {
-                       get {
-                               if (data == null)
-                                       return -1;
-                               GenericStack page1 = items.FindByName ("page1") as GenericStack;
-                               if (page1 == null)
-                                       return -1;
-
-                               return page1.Orientation == Orientation.Horizontal ?
-                                       (data as ICollection)?.Count < itemPerPage ?
-                                       -1:
-                                       (int)Math.Ceiling ((double)page1.Slot.Width / (double)itemPerPage * (double)((data as ICollection)?.Count+1)):
-                                       (data as ICollection)?.Count < itemPerPage ?
-                                       -1:
-                                       (int)Math.Ceiling ((double)page1.Slot.Height / (double)itemPerPage * (double)((data as ICollection)?.Count+1));
-                       }
-               }
-               internal virtual void itemClick(object sender, MouseButtonEventArgs e){
-                       SelectedIndex = (int)((IList)data)?.IndexOf((sender as Widget).DataSource);
-               }
-
-               bool emitHelperIsAlreadyExpanded (Widget go){
-                       if (nodes.Contains (go))
-                               return true;
-                       nodes.Add (go);
-                       return false;
-               }
-
-               protected override void Dispose (bool disposing)
-               {
-                       if (disposing && loadingThread != null)
-                               loadingThread.Cancel ();
-                       base.Dispose (disposing);
-               }
-
-               public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
-               {
-                       base.OnDataSourceChanged (sender, e);
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/TestCairoPatch.cs b/Crow/src/GraphicObjects/TestCairoPatch.cs
deleted file mode 100644 (file)
index f8294a3..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-//
-// TestCairoPatch.cs
-//
-// Author:
-//       jp <>
-//
-// 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 Crow.Cairo;
-
-namespace Crow
-{
-       public class TestCairoPatch : Widget
-       {
-               void computeControlPoints (
-                       double xc, double yc,
-                       double x1, double y1,
-                       out double x2, out double y2,
-                       out double x3, out double y3,
-                       double x4, double y4){
-                       double ax = x1 - xc;
-                       double ay = y1 - yc;
-                       double bx = x4 - xc;
-                       double byy = y4 - yc;
-                       double q1 = ax * ax + ay * ay;
-                       double q2 = q1 + ax * bx + ay * byy;
-                       double k2 = 4.0/3.0 * (Math.Sqrt(2.0 * q1 * q2) - q2) / (ax * byy - ay * bx);
-
-
-                       x2 = xc + ax - k2 * ay;
-                       y2 = yc + ay + k2 * ax;
-                       x3 = xc + bx + k2 * byy;
-                       y3 = yc + byy - k2 * bx;
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       double radius = Math.Min (ClientRectangle.Width, ClientRectangle.Height) / 2;
-
-                       double pi3 = Math.PI / 3.0;
-
-                       MeshPattern mp = new MeshPattern ();
-
-                       double x1 = radius,y1 = 0,
-                       x2 = 0, y2 = 0, x3 = 0, y3 = 0, x4 = 0, y4 = 0,
-                       xc = radius,yc = radius;
-
-                       double dx = Math.Sin (pi3) * radius;
-                       double dy = Math.Cos (pi3) * radius;
-
-                       mp.BeginPatch ();
-                       mp.MoveTo (xc, yc);
-                       mp.LineTo (x1, y1);
-                       x4 = xc + dx;
-                       y4 = yc - dy;
-                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
-                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
-
-                       mp.SetCornerColorRGB (0, 1, 1, 1);
-                       mp.SetCornerColorRGB (1, 1, 0, 0);
-                       mp.SetCornerColorRGB (2, 1, 1, 0);
-
-                       x1 = x4;
-                       y1 = y4;
-                       y4 = yc + dy;
-
-                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
-                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
-
-                       mp.SetCornerColorRGB (3, 0, 1, 0);
-                       mp.EndPatch ();
-
-                       x1 = x4;
-                       y1 = y4;
-                       x4 = xc;
-                       y4 = yc * 2.0;
-
-                       mp.BeginPatch ();
-                       mp.MoveTo (xc, yc);
-                       mp.LineTo (x1, y1);
-                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
-                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
-
-                       mp.SetCornerColorRGB (0, 1, 1, 1);
-                       mp.SetCornerColorRGB (1, 0, 1, 0);
-                       mp.SetCornerColorRGB (2, 0, 1, 1);
-
-                       x1 = x4;
-                       y1 = y4;
-                       x4 = xc-dx;
-                       y4 = yc+dy;
-
-                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
-                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
-
-                       mp.SetCornerColorRGB (3, 0, 0, 1);
-                       mp.EndPatch ();
-
-                       x1 = x4;
-                       y1 = y4;
-                       y4 = yc - dy;
-
-                       mp.BeginPatch ();
-                       mp.MoveTo (xc, yc);
-                       mp.LineTo (x1, y1);
-                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
-                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
-
-                       mp.SetCornerColorRGB (0, 1, 1, 1);
-                       mp.SetCornerColorRGB (1, 0, 0, 1);
-                       mp.SetCornerColorRGB (2, 1, 0, 1);
-
-                       x1 = x4;
-                       y1 = y4;
-                       x4 = radius;
-                       y4 = 0;
-
-                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
-                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
-
-                       mp.SetCornerColorRGB (3, 1, 0, 0);
-                       mp.EndPatch ();
-
-                       gr.SetSource (mp);
-                       gr.Paint ();
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/TextBox.cs b/Crow/src/GraphicObjects/TextBox.cs
deleted file mode 100644 (file)
index 71fd620..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-//
-// TextBox.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 Crow.Cairo;
-using System.Diagnostics;
-using System.Xml.Serialization;
-
-namespace Crow
-{
-    public class TextBox : Label
-    {
-               #region CTOR
-               protected TextBox() : base(){}
-               public TextBox(Interface iface) : base(iface)
-               { }
-//             public TextBox(string _initialValue)
-//                     : base(_initialValue)
-//             {
-//
-//             }
-               #endregion
-
-               #region GraphicObject overrides
-               [XmlIgnore]public override bool HasFocus   //trigger update when lost focus to errase text beam
-        {
-            get
-            {
-                return base.HasFocus;
-            }
-            set
-            {
-                base.HasFocus = value;
-                RegisterForRedraw();
-            }
-        }
-
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-                       FontExtents fe = gr.FontExtents;
-               }
-               #endregion
-                       
-        #region Keyboard handling
-               public override void onKeyDown (object sender, KeyEventArgs e)
-               {
-                       base.onKeyDown (sender, e);
-
-                       Key key = e.Key;
-
-                       switch (key)
-                       {
-                       case Key.BackSpace:
-                               if (CurrentPosition == 0)
-                                       return;
-                               this.DeleteChar();
-                               break;
-                       case Key.Clear:
-                               break;
-                       case Key.Delete:
-                               if (selectionIsEmpty) {
-                                       if (!MoveRight ())
-                                               return;
-                               }else if (IFace.Shift)
-                                       IFace.Clipboard = this.SelectedText;
-                               this.DeleteChar ();
-                               break;
-                       case Key.KP_Enter:
-                       case Key.Return:
-                               if (!selectionIsEmpty)
-                                       this.DeleteChar ();
-                               if (Multiline)
-                                       this.InsertLineBreak ();
-                               else
-                                       OnTextChanged(this,new TextChangeEventArgs(Text));
-                               break;
-                       case Key.Escape:
-                               Text = "";
-                               CurrentColumn = 0;
-                               SelRelease = -1;
-                               break;
-                       case Key.Home:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = new Point (CurrentColumn, CurrentLine);
-                                       if (IFace.Ctrl)
-                                               CurrentLine = 0;
-                                       CurrentColumn = 0;
-                                       SelRelease = new Point (CurrentColumn, CurrentLine);
-                                       break;
-                               }
-                               SelRelease = -1;
-                               if (IFace.Ctrl)
-                                       CurrentLine = 0;
-                               CurrentColumn = 0;
-                               break;
-                       case Key.End:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       if (IFace.Ctrl)
-                                               CurrentLine = int.MaxValue;
-                                       CurrentColumn = int.MaxValue;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               if (IFace.Ctrl)
-                                       CurrentLine = int.MaxValue;
-                               CurrentColumn = int.MaxValue;
-                               break;
-                       case Key.Insert:
-                               if (IFace.Shift)
-                                       this.Insert (IFace.Clipboard);
-                               else if (IFace.Ctrl && !selectionIsEmpty)
-                                       IFace.Clipboard = this.SelectedText;
-                               break;
-                       case Key.Left:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = new Point(CurrentColumn, CurrentLine);
-                                       if (IFace.Ctrl)
-                                               GotoWordStart ();
-                                       else if (!MoveLeft ())
-                                               return;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               if (IFace.Ctrl)
-                                       GotoWordStart ();
-                               else
-                                       MoveLeft();
-                               break;
-                       case Key.Right:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       if (IFace.Ctrl)
-                                               GotoWordEnd ();
-                                       else if (!MoveRight ())
-                                               return;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               if (IFace.Ctrl)
-                                       GotoWordEnd ();
-                               else
-                                       MoveRight ();
-                               break;
-                       case Key.Up:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       CurrentLine--;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               CurrentLine--;
-                               break;
-                       case Key.Down:
-                               if (IFace.Shift) {
-                                       if (selectionIsEmpty)
-                                               SelBegin = CurrentPosition;
-                                       CurrentLine++;
-                                       SelRelease = CurrentPosition;
-                                       break;
-                               }
-                               SelRelease = -1;
-                               CurrentLine++;                          
-                               break;
-                       case Key.Menu:
-                               break;
-                       case Key.Num_Lock:
-                               break;
-                       case Key.Page_Down:                             
-                               break;
-                       case Key.Page_Up:
-                               break;
-                       case Key.Tab:
-                               this.Insert ("\t");
-                               break;
-                       default:
-                               break;
-                       }
-
-                       RegisterForGraphicUpdate();
-               }
-               public override void onKeyPress (object sender, KeyPressEventArgs e)
-               {
-                       base.onKeyPress (sender, e);
-
-                       this.Insert (e.KeyChar.ToString());
-
-                       SelRelease = -1;
-                       SelBegin = new Point(CurrentColumn, SelBegin.Y);
-
-                       RegisterForGraphicUpdate();
-               }
-        #endregion
-       } 
-}
diff --git a/Crow/src/GraphicObjects/TextRun.cs b/Crow/src/GraphicObjects/TextRun.cs
deleted file mode 100644 (file)
index f784f90..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-//
-// TextRun.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.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Crow.Cairo;
-using System.Text.RegularExpressions;
-using System.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
-       [DesignIgnore]
-       public class TextRun : Widget
-       {
-               #region CTOR
-               protected TextRun () : base(){}
-               public TextRun (Interface iface) : base (iface){}
-               #endregion
-
-               //TODO:change protected to private
-
-               #region private and protected fields
-               protected string _text = "label";
-               Alignment _textAlignment = Alignment.Left;
-               bool horizontalStretch = false;
-               bool verticalStretch = false;
-               bool _multiline;
-               bool wordWrap;
-               protected Rectangle rText;
-               protected float widthRatio = 1f;
-               protected float heightRatio = 1f;
-               protected FontExtents fe;
-               protected TextExtents te;
-               #endregion
-
-
-               
-               [DefaultValue (Alignment.Left)]
-               public Alignment TextAlignment {
-                       get { return _textAlignment; }
-                       set { _textAlignment = value; }
-               }
-               
-               [DefaultValue (false)]
-               public virtual bool HorizontalStretch {
-                       get { return horizontalStretch; }
-                       set {
-                               if (horizontalStretch == value)
-                                       return;
-                               horizontalStretch = value;
-                               RegisterForRedraw ();
-                               NotifyValueChanged ("HorizontalStretch", horizontalStretch);
-                       }
-               }
-               
-               [DefaultValue (false)]
-               public virtual bool VerticalStretch {
-                       get { return verticalStretch; }
-                       set {
-                               if (verticalStretch == value)
-                                       return;
-                               verticalStretch = value;
-                               RegisterForRedraw ();
-                               NotifyValueChanged ("VerticalStretch", verticalStretch);
-                       }
-               }
-               
-               [DefaultValue ("label")]
-               public string Text {
-                       get {
-                               return lines == null ?
-                                       _text : lines.Aggregate ((i, j) => i + Interface.LineBreak + j);
-                       }
-                       set {
-                               if (_text == value)
-                                       return;
-
-                               RegisterForGraphicUpdate ();
-
-                               _text = value;
-
-                               if (string.IsNullOrEmpty (_text))
-                                       _text = "";
-
-                               lines = getLines;
-                       }
-               }
-               
-               [DefaultValue (false)]
-               public bool Multiline {
-                       get { return _multiline; }
-                       set {
-                               _multiline = value;
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               
-               [DefaultValue (false)]
-               public bool WordWrap {
-                       get {
-                               return wordWrap;
-                       }
-                       set {
-                               if (wordWrap == value)
-                                       return;
-                               wordWrap = value;
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-
-               List<string> lines;
-               List<string> getLines {
-                       get {
-                               return _multiline ?
-                                       Regex.Split (_text, "\r\n|\r|\n").ToList () :
-                                       new List<string> (new string [] { _text });
-                       }
-               }
-
-               #region GraphicObject overrides
-               protected override int measureRawSize (LayoutingType lt)
-               {
-                       if (lines == null)
-                               lines = getLines;
-                               
-                       using (Context gr = new Context (IFace.surf)) {
-                               //Cairo.FontFace cf = gr.GetContextFontFace ();
-
-                               gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
-                               gr.SetFontSize (Font.Size);
-
-
-                               fe = gr.FontExtents;
-                               te = new TextExtents ();
-
-                               if (lt == LayoutingType.Height) {
-                                       int lc = lines.Count;
-                                       //ensure minimal height = text line height
-                                       if (lc == 0)
-                                               lc = 1;
-
-                                       return (int)(fe.Height * lc) + Margin * 2;
-                               }
-
-                               foreach (string s in lines) {
-                                       string l = s.Replace("\t", new String (' ', Interface.TAB_SIZE));
-                                       TextExtents tmp = gr.TextExtents (l);
-                                       if (tmp.XAdvance > te.XAdvance)
-                                               te = tmp;
-                               }
-                               return (int)Math.Ceiling (te.XAdvance) + Margin * 2;
-                       }
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
-                       gr.SetFontSize (Font.Size);
-                       gr.FontOptions = Interface.FontRenderingOptions;
-                       gr.Antialias = Interface.Antialias;
-
-                       rText = new Rectangle (new Size (
-                               measureRawSize (LayoutingType.Width), measureRawSize (LayoutingType.Height)));
-                       rText.Width -= 2 * Margin;
-                       rText.Height -= 2 * Margin;
-
-                       widthRatio = 1f;
-                       heightRatio = 1f;
-
-                       Rectangle cb = ClientRectangle;
-
-                       //ignore text alignment if size to content = true
-                       //or if text size is larger than client bounds
-                       if (Width < 0 || Height < 0 || rText.Width > cb.Width) {
-                               rText.X = cb.X;
-                               rText.Y = cb.Y;
-                       } else {
-                               if (horizontalStretch) {
-                                       widthRatio = (float)cb.Width / rText.Width;
-                                       if (!verticalStretch)
-                                               heightRatio = widthRatio;
-                               }
-                               if (verticalStretch) {
-                                       heightRatio = (float)cb.Height / rText.Height;
-                                       if (!horizontalStretch)
-                                               widthRatio = heightRatio;
-                               }
-
-                               rText.Width = (int)(widthRatio * cb.Width);
-                               rText.Height = (int)(heightRatio * cb.Height);
-
-                               switch (TextAlignment) {
-                               case Alignment.TopLeft:     //ok
-                                       rText.X = cb.X;
-                                       rText.Y = cb.Y;
-                                       break;
-                               case Alignment.Top:   //ok                                              
-                                       rText.Y = cb.Y;
-                                       rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
-                                       break;
-                               case Alignment.TopRight:    //ok
-                                       rText.Y = cb.Y;
-                                       rText.X = cb.Right - rText.Width;
-                                       break;
-                               case Alignment.Left://ok
-                                       rText.X = cb.X;
-                                       rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
-                                       break;
-                               case Alignment.Right://ok
-                                       rText.X = cb.X + cb.Width - rText.Width;
-                                       rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
-                                       break;
-                               case Alignment.Bottom://ok
-                                       rText.X = cb.Width / 2 - rText.Width / 2;
-                                       rText.Y = cb.Height - rText.Height;
-                                       break;
-                               case Alignment.BottomLeft://ok
-                                       rText.X = cb.X;
-                                       rText.Y = cb.Bottom - rText.Height;
-                                       break;
-                               case Alignment.BottomRight://ok
-                                       rText.Y = cb.Bottom - rText.Height;
-                                       rText.X = cb.Right - rText.Width;
-                                       break;
-                               case Alignment.Center://ok
-                                       rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
-                                       rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
-                                       break;
-                               }
-                       }
-
-                       gr.FontMatrix = new Matrix (widthRatio * Font.Size, 0, 0, heightRatio * Font.Size, 0, 0);
-
-
-                       int curLineCount = 0;
-                       for (int i = 0; i < lines.Count; i++) {
-                               string l = lines [i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
-                               List<string> wl = new List<string> ();
-                               int lineLength = (int)gr.TextExtents (l).XAdvance;
-
-                               if (wordWrap && lineLength > cb.Width) {
-                                       string tmpLine = "";
-                                       int curChar = 0;
-                                       while (curChar < l.Length) {
-                                               tmpLine += l [curChar];
-                                               if ((int)gr.TextExtents (tmpLine).XAdvance > cb.Width) {
-                                                       tmpLine = tmpLine.Remove (tmpLine.Length - 1);
-                                                       wl.Add (tmpLine);
-                                                       tmpLine = "";
-                                                       continue;
-                                               }
-                                               curChar++;
-                                       }
-                                       wl.Add (tmpLine);
-                               } else
-                                       wl.Add (l);
-
-                               foreach (string ll in wl) {
-                                       lineLength = (int)gr.TextExtents (ll).XAdvance;
-
-
-                                       if (string.IsNullOrWhiteSpace (ll)) {
-                                               curLineCount++;
-                                               continue;
-                                       }
-
-                                       Foreground.SetAsSource (gr);
-                                       gr.MoveTo (rText.X, rText.Y + fe.Ascent + fe.Height * curLineCount);
-
-                                       gr.ShowText (ll);
-                                       gr.Fill ();
-
-                                       curLineCount++;
-                               }
-                       }
-               }
-               #endregion
-       }
-}
diff --git a/Crow/src/GraphicObjects/TreeView.cs b/Crow/src/GraphicObjects/TreeView.cs
deleted file mode 100644 (file)
index af86ab7..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-// TreeView.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.Xml.Serialization;
-using System.Diagnostics;
-using System.ComponentModel;
-
-namespace Crow
-{
-       //treeview expect expandable child (or not)
-       //if their are expandable, some functions and events are added
-       public class TreeView : TemplatedGroup
-       {
-               Widget selectedItemContainer = null;
-               bool isRoot;
-
-               #region CTOR
-               protected TreeView() : base(){}
-               public TreeView (Interface iface) : base(iface)
-               {
-               }
-               #endregion
-
-               [DefaultValue(false)]
-               public virtual bool IsRoot {
-                       get { return isRoot; }
-                       set {
-                               if (isRoot == value)
-                                       return;
-                               isRoot = value;
-                               NotifyValueChanged ("IsRoot", isRoot);
-                       }
-               }
-               [XmlIgnore]public override object SelectedItem {
-                       get {
-                               return selectedItemContainer == null ?
-                                       "" : selectedItemContainer.DataSource;
-                       }
-               }
-
-               internal override void itemClick (object sender, MouseButtonEventArgs e)
-               {
-                       Widget tmp = sender as Widget;
-                       //if (!tmp.HasFocus)
-                       //      return;
-                       /*if (selectedItemContainer != null) {
-                               selectedItemContainer.Foreground = Color.Transparent;
-                               selectedItemContainer.Background = Color.Transparent;
-                       }*/
-                       selectedItemContainer = tmp;
-                       //selectedItemContainer.Foreground = SelectionForeground;
-                       //selectedItemContainer.Background = SelectionBackground;
-                       NotifyValueChanged ("SelectedItem", SelectedItem);
-                       raiseSelectedItemChanged ();
-               }
-
-               void onExpandAll_MouseClick (object sender, MouseButtonEventArgs e)
-               {
-                       ExpandAll ();
-               }
-
-               public void ExpandAll(){
-                       foreach (Group grp in items.Children) {
-                               foreach (Widget go in grp.Children) {
-                                       Expandable exp = go as Expandable;
-                                       if (exp == null)
-                                               continue;
-                                       TreeView subTV = exp.FindByName ("List") as TreeView;
-                                       if (subTV == null)
-                                               continue;
-                                       EventHandler handler = null;
-                                       handler = delegate(object sender, EventArgs e) {
-                                               TreeView tv = sender as TreeView;
-                                               tv.Loaded -= handler;
-                                               tv.ExpandAll ();
-                                       };
-                                       subTV.Loaded += handler;
-                                       exp.IsExpanded = true;
-                               }
-                       }
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Trend.cs b/Crow/src/GraphicObjects/Trend.cs
deleted file mode 100644 (file)
index b62fd2f..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-//
-// Trend.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.Collections.Generic;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using Crow.Cairo;
-
-namespace Crow
-{
-       public class Trend : Widget
-       {
-               #region private fields
-               double minValue, maxValue, lowThreshold, highThreshold;
-               Fill lowThresholdFill, highThresholdFill;
-               int nbValues;
-               List<double> values = new List<double>();
-               #endregion
-
-
-
-               public virtual void AddValue(double _value)
-               {
-                       values.Add (_value);
-                       while (values.Count > nbValues)
-                               values.RemoveAt (0);
-                       RegisterForRedraw ();
-               }
-               #region CTOR
-               protected Trend () : base()
-               {
-               }
-               #endregion
-               [XmlIgnore]public virtual int NewValue {
-                       set {
-                               AddValue (value);
-                       }
-               }
-               [DefaultValue(400)]
-               public virtual int NbValues {
-                       get { return nbValues; }
-                       set {
-                               if (nbValues == value)
-                                       return;
-
-                               nbValues = value;
-                               NotifyValueChanged ("NbValues", minValue);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(0.0)]
-               public virtual double Minimum {
-                       get { return minValue; }
-                       set {
-                               if (minValue == value)
-                                       return;
-
-                               minValue = value;
-                               NotifyValueChanged ("Minimum", minValue);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(100.0)]
-               public virtual double Maximum
-               {
-                       get { return maxValue; }
-                       set {
-                               if (maxValue == value)
-                                       return;
-
-                               maxValue = value;
-                               NotifyValueChanged ("Maximum", maxValue);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(1.0)]
-               public virtual double LowThreshold {
-                       get { return lowThreshold; }
-                       set {
-                               if (lowThreshold == value)
-                                       return;
-                               lowThreshold = value;
-                               NotifyValueChanged ("LowThreshold", lowThreshold);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               [DefaultValue(80.0)]
-               public virtual double HighThreshold {
-                       get { return highThreshold; }
-                       set {
-                               if (highThreshold == value)
-                                       return;
-                               highThreshold = value;
-                               NotifyValueChanged ("HighThreshold", highThreshold);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               [DefaultValue("DarkRed")]
-               public virtual Fill LowThresholdFill {
-                       get { return lowThresholdFill; }
-                       set {
-                               if (lowThresholdFill == value)
-                                       return;
-                               lowThresholdFill = value;
-                               NotifyValueChanged ("LowThresholdFill", lowThresholdFill);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue("DarkGreen")]
-               public virtual Fill HighThresholdFill {
-                       get { return highThresholdFill; }
-                       set {
-                               if (highThresholdFill == value)
-                                       return;
-                               highThresholdFill = value;
-                               NotifyValueChanged ("HighThresholdFill", highThresholdFill);
-                               RegisterForRedraw ();
-                       }
-               }
-               protected override void onDraw (Context gr)
-               {
-                       base.onDraw (gr);
-
-                       if (values.Count == 0)
-                               return;
-                       Rectangle r = ClientRectangle;
-
-                       int i = values.Count -1;
-
-                       double ptrX = (double)r.Right;
-                       double scaleY = (double)r.Height / (Maximum - Minimum);
-                       double stepX = (double)r.Width / (double)(nbValues-1);
-
-                       gr.LineWidth = 1.0;
-                       gr.SetDash (new double[]{ 1.0 },0.0);
-
-
-
-                       LowThresholdFill.SetAsSource (gr);
-                       gr.MoveTo (r.Left, r.Bottom - LowThreshold * scaleY);
-                       gr.LineTo (r.Right, r.Bottom - LowThreshold * scaleY);
-//                     gr.Rectangle (r.Left, r.Bottom - LowThreshold * scaleY, r.Width, LowThreshold * scaleY);
-                       gr.Stroke();
-
-                       HighThresholdFill.SetAsSource (gr);
-                       gr.MoveTo (r.Left, (Maximum - HighThreshold) * scaleY);
-                       gr.LineTo (r.Right, (Maximum - HighThreshold) * scaleY);
-//                     gr.Rectangle (r.Left, r.Top, r.Width, (Maximum - HighThreshold) * scaleY);
-                       gr.Stroke();
-
-                       gr.MoveTo (ptrX, values [i] * scaleY);
-
-                       Foreground.SetAsSource (gr);
-                       gr.SetDash (new double[]{ }, 0.0);
-
-                       while (i >= 0) {
-                                       gr.LineTo (ptrX, r.Bottom - values [i] * scaleY);
-                               ptrX -= stepX;
-                               i--;
-                       }
-                       gr.Stroke ();
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/VerticalStack.cs b/Crow/src/GraphicObjects/VerticalStack.cs
deleted file mode 100644 (file)
index cf0a251..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// VerticalStack.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.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Crow
-{
-       /// <summary>
-       /// group control stacking its children vertically
-       /// </summary>
-    public class VerticalStack : GenericStack
-    {
-               #region CTOR
-               protected VerticalStack() : base(){}
-               public VerticalStack(Interface iface) : base(iface)
-        {
-        }
-               #endregion
-
-        [XmlIgnore]
-        public override Orientation Orientation
-        {
-            get { return Orientation.Vertical; }            
-        }
-
-
-    }
-}
diff --git a/Crow/src/GraphicObjects/Widget.cs b/Crow/src/GraphicObjects/Widget.cs
deleted file mode 100644 (file)
index d6c3a96..0000000
+++ /dev/null
@@ -1,2032 +0,0 @@
-//
-// GraphicObject.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.Collections.Generic;
-using System.ComponentModel;
-using System.Xml.Serialization;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.CompilerServices;
-using Crow.Cairo;
-using System.Diagnostics;
-using Crow.IML;
-using System.Threading;
-
-
-#if DESIGN_MODE
-using System.Xml;
-using System.IO;
-#endif
-
-namespace Crow
-{
-       /// <summary>
-       /// The base class for all the graphic tree elements.
-       /// </summary>
-       public class Widget : ILayoutable, IValueChange, IDisposable
-       {
-               internal ReaderWriterLockSlim parentRWLock = new ReaderWriterLockSlim();
-               #if DEBUG_LOG
-               //0 is the main graphic tree, for other obj tree not added to main tree, it range from 1->n
-               //useful to track events for obj shown later, not on start, or never added to main tree
-               public int treeIndex;
-               public int yIndex;//absolute index in the graphic tree for debug draw
-               public int xLevel;//x increment for debug draw
-               #endif
-               #if DESIGN_MODE
-               static MethodInfo miDesignAddDefLoc = typeof(Widget).GetMethod("design_add_style_location",
-                       BindingFlags.Instance | BindingFlags.NonPublic);
-               static MethodInfo miDesignAddValLoc = typeof(Widget).GetMethod("design_add_iml_location",
-                       BindingFlags.Instance | BindingFlags.NonPublic);
-               
-               public volatile bool design_HasChanged = false;
-               public string design_id;
-               public int design_line;
-               public int design_column;
-               public string design_imlPath;
-               public bool design_isTGItem = false;//true if this is a templated item's root
-               public Dictionary<string,string> design_iml_values = new Dictionary<string, string>();
-               public Dictionary<string,string> design_style_values = new Dictionary<string, string>();
-               //public Dictionary<string,FileLocation> design_iml_locations = new Dictionary<string, FileLocation>();
-               public Dictionary<string,FileLocation> design_style_locations = new Dictionary<string, FileLocation>();
-
-               internal void design_add_style_location (string memberName, string path, int line, int col) {                   
-                       if (design_style_locations.ContainsKey(memberName)){
-                               Console.WriteLine ("default value localtion already set for {0}{1}.{2}", this.GetType().Name, this.design_id, memberName);
-                               return;
-                       }
-                       design_style_locations.Add(memberName, new FileLocation(path,line,col));
-               }
-//             internal void design_add_iml_location (string memberName, string path, int line, int col) {
-//                     if (design_iml_locations.ContainsKey(memberName)){
-//                             Console.WriteLine ("IML value localtion already set for {0}{1}.{2}", this.GetType().Name, this.design_id, memberName);
-//                             return;
-//                     }
-//                     design_iml_locations.Add(memberName, new FileLocation(path,line,col));
-//             }
-                       
-               public virtual bool FindByDesignID(string designID, out Widget go){
-                       go = null;
-                       if (this.design_id == designID){
-                               go = this;
-                               return true;
-                       }
-                       return false;
-               }
-
-               public string GetIML(){
-                       XmlDocument doc = new XmlDocument( );
-
-                       using (StringWriter sw = new StringWriter ()) {
-                               XmlWriterSettings settings = new XmlWriterSettings {
-                                       Indent = true,
-                                       IndentChars = "\t",
-                               };
-                               using (XmlWriter xtw = XmlWriter.Create (sw, settings)) {
-                                       //(1) the xml declaration is recommended, but not mandatory
-                                       XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration ("1.0", "UTF-8", null);
-                                       doc.InsertBefore (xmlDeclaration, null);
-                                       getIML (doc, (XmlNode)doc);
-                                       doc.WriteTo (xtw);
-                               }
-                               this.design_HasChanged = false;
-                               return sw.ToString ();
-                       }
-               }
-
-               public virtual void getIML(XmlDocument doc, XmlNode parentElem) {
-                       if (this.design_isTGItem)
-                               return;
-                       
-                       XmlElement xe = doc.CreateElement(this.GetType().Name);
-
-                       foreach (KeyValuePair<string,string> kv in design_iml_values) {
-                               XmlAttribute xa = doc.CreateAttribute (kv.Key);
-                               xa.Value = kv.Value;
-                               xe.Attributes.Append (xa);
-                       }
-
-                       parentElem.AppendChild (xe);
-               }
-               public Surface CreateIcon (int dragIconSize = 32) {
-                       ImageSurface di = new ImageSurface (Format.Argb32, dragIconSize, dragIconSize);
-                       using (Context ctx = new Context (di)) {
-                               double div = Math.Max (LastPaintedSlot.Width, LastPaintedSlot.Height);
-                               double s = (double)dragIconSize / div;
-                               ctx.Scale (s, s);
-                               if (bmp == null)
-                                       this.onDraw (ctx);
-                               else {
-                                       if (LastPaintedSlot.Width>LastPaintedSlot.Height)
-                                               ctx.SetSourceSurface (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2);
-                                       else
-                                               ctx.SetSourceSurface (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0);
-                                       ctx.Paint ();
-                               }
-                       }
-                       return di;
-               }
-        public string DesignName {
-            get { return GetType ().Name + design_id; }
-        }
-               #endif
-
-               #region IDisposable implementation
-               protected bool disposed = false;
-
-               public void Dispose(){  
-                       Dispose(true);  
-                       GC.SuppressFinalize(this);  
-               }  
-               ~Widget(){
-                       Console.WriteLine(this.ToString() + " not disposed by user");
-                       Dispose(false);
-               }
-               protected virtual void Dispose(bool disposing){
-                       if (disposed){
-                               #if DEBUG_DISPOSE
-                               Console.WriteLine ("Trying to dispose already disposed obj: {0}", this.ToString());
-                               #endif
-                               return;
-                       }
-
-                       if (disposing) {
-                               #if DEBUG_DISPOSE
-                               Console.WriteLine ("Disposing: {0}", this.ToString());
-                               //if ()
-                               //throw new Exception("Trying to dispose an object queued for Redraw: " + this.ToString());
-                               #endif
-
-                               unshownPostActions ();
-
-                               if (!localDataSourceIsNull)
-                                       DataSource = null;
-
-                               parentRWLock.EnterWriteLock();
-                               parent = null;
-                               parentRWLock.ExitWriteLock();
-                       } else
-                               Debug.WriteLine ("!!! Finalized by GC: {0}", this.ToString ());
-                       Clipping?.Dispose ();
-                       bmp?.Dispose ();
-                       disposed = true;
-               }  
-               #endregion
-
-               #if DEBUG_LOG
-               internal static List<GraphicObject> GraphicObjects = new List<GraphicObject>();
-               #endif
-
-               //internal bool isPopup = false;
-               //public Widget focusParent {
-               //      get { return (isPopup ? LogicalParent : parent) as Widget; }
-               //}
-
-               /// <summary>
-               /// interface this widget is bound to, this should not be changed once the instance is created
-               /// </summary>
-               public Interface IFace = null;
-
-               /// <summary>
-               /// contains the dirty rectangles in the coordinate system of the cache. those dirty zones
-               /// are repeated at each cached levels of the tree with correspondig coordinate system. This is done
-               /// in a dedicated step of the update between layouting and drawing.
-               /// </summary>
-               public Region Clipping;
-
-               #region IValueChange implementation
-               /// <summary>
-               /// Raise to notify that the value of a property has changed, the binding system
-               /// rely mainly on this event. the member name may not be present in the class, this is 
-               /// used in **propertyless** bindings, this allow to raise custom named events without needing
-               /// to create an new one in the class or a new property.
-               /// </summary>
-               public event EventHandler<ValueChangeEventArgs> ValueChanged;
-               /// <summary>
-               /// Helper function to raise the value changed event
-               /// </summary>
-               public virtual void NotifyValueChanged(string MemberName, object _value)
-               {
-                       //Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value);
-                       ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value));
-               }
-               #endregion
-
-               #region CTOR
-               /// <summary>
-               /// default private parameter less constructor use in instantiators, it should not be used
-               /// when creating widget from code because widgets has to be bound to an interface before any other
-               /// action.
-               /// </summary>
-               protected Widget () {
-                       Clipping = new Region ();
-                       #if DEBUG_LOG
-                       GraphicObjects.Add (this);
-                       DebugLog.AddEvent(DbgEvtType.GOClassCreation, this);
-                       #endif                  
-               }
-               /// <summary>
-               /// This constructor **must** be used when creating widget from code.
-               ///
-               /// When creating new widgets derived from GraphicObject, both parameterless and this constructors are
-               /// facultatives, the compiler will create the parameterless one automaticaly if no other one exists.
-               /// But if you intend to be able to create instances of the new widget in code and override the constructor
-               /// with the Interface parameter, you **must** also provide the override of the parameterless constructor because
-               /// compiler will not create it automatically because of the presence of the other one.
-               /// </summary>
-               /// <param name="iface">Iface.</param>
-               public Widget (Interface iface) : this()
-               {
-                       IFace = iface;
-                       Initialize ();
-               }
-               #endregion
-               //internal bool initialized = false;
-               /// <summary>
-               /// Initialize this Graphic object instance by setting style and default values and loading template if required
-               /// </summary>
-               public virtual void Initialize(){
-                       loadDefaultValues ();
-               }
-               #region private fields
-               LayoutingType registeredLayoutings = LayoutingType.All;
-               ILayoutable logicalParent;
-               ILayoutable parent;
-               string name;
-               Fill background = Color.Transparent;
-               Fill foreground = Color.White;
-               Font font = "sans, 10";
-               protected Measure width, height;
-               int left, top;
-               double cornerRadius;
-               int margin;
-               bool focusable ;
-               bool hasFocus;
-               bool isActive;
-               bool isHover;
-               bool mouseRepeat;
-               MouseCursor mouseCursor = MouseCursor.Arrow;
-               protected bool isVisible = true;
-               bool isEnabled = true;
-               VerticalAlignment verticalAlignment = VerticalAlignment.Center;
-               HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center;
-               Size maximumSize = "0,0";
-               Size minimumSize = "0,0";
-               bool cacheEnabled;
-               bool clipToClientRect = true;
-               Type dataSourceType;
-               protected object dataSource;
-               bool rootDataLevel;
-               string style;
-               object tag;
-               bool isDragged;
-               bool allowDrag;
-               bool allowDrop;
-               string tooltip;
-               IList<Command> contextCommands;
-               #endregion
-
-               #region public fields
-               /// <summary>
-               /// Current size and position computed during layouting pass
-               /// </summary>
-               public Rectangle Slot = new Rectangle ();
-               /// <summary>
-               /// keep last slot components for each layouting pass to track
-               /// changes and trigger update of other component accordingly
-               /// </summary>
-               public Rectangle LastSlots;
-               /// <summary>
-               /// keep last slot painted on screen to clear traces if moved or resized
-               /// 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 IsQueueForClipping = false;
-               /// <summary>drawing Cache, if null, a redraw is done, cached or not</summary>
-               public Surface bmp;
-               public bool IsDirty = true;
-               /// <summary>
-               /// This size is computed on each child' layout changes.
-               /// In stacking widget, it is used to compute the remaining space for the stretched
-               /// widget inside the stack, which is never added to the contentSize, instead, its size
-               /// is deducted from (parent.ClientRectangle - contentSize)
-               /// </summary>
-               internal Size contentSize;
-               #endregion
-
-               #region ILayoutable
-               [XmlIgnore]public LayoutingType RegisteredLayoutings { get { return registeredLayoutings; } set { registeredLayoutings = value; } }
-               //TODO: it would save the recurent cost of a cast in event bubbling if parent type was GraphicObject
-               //              or we could add to the interface the mouse events
-               /// <summary>
-               /// Parent in the graphic tree, used for rendering and layouting
-               /// </summary>
-               [XmlIgnore]public virtual ILayoutable Parent {
-                       get { return parent; }
-                       set {
-                               if (parent == value)
-                                       return;
-                               DataSourceChangeEventArgs e = new DataSourceChangeEventArgs (parent, value);
-
-                               parentRWLock.EnterWriteLock();
-                               parent = value;
-                               Slot = LastSlots = default(Rectangle);
-                               parentRWLock.ExitWriteLock();
-                                                                       
-                               onParentChanged (this, e);
-                       }
-               }
-               /// <summary>
-               /// Mouse routing need to go back to logical parent for popups
-               /// </summary>
-               public Widget FocusParent => (parent is Interface ? LogicalParent : parent) as Widget; 
-
-               [XmlIgnore]public ILayoutable LogicalParent {
-                       get { return logicalParent == null ? Parent : logicalParent; }
-                       set {
-                               if (logicalParent == value)
-                                       return;
-                               if (logicalParent is Widget)
-                                       (logicalParent as Widget).DataSourceChanged -= onLogicalParentDataSourceChanged;
-                               DataSourceChangeEventArgs dsce = new DataSourceChangeEventArgs (LogicalParent, null);
-                               logicalParent = value;
-                               dsce.NewDataSource = LogicalParent;
-                               if (logicalParent is Widget)
-                                       (logicalParent as Widget).DataSourceChanged += onLogicalParentDataSourceChanged;
-                               onLogicalParentChanged (this, dsce);
-                       }
-               }
-               [XmlIgnore]public virtual Rectangle ClientRectangle {
-                       get {
-                               Rectangle cb = Slot.Size;
-                               cb.Inflate ( - margin);
-                               return cb;
-                       }
-               }
-               public virtual Rectangle ContextCoordinates(Rectangle r){
-                       Widget go = Parent as Widget;
-                       if (go == null)
-                               return r + Parent.ClientRectangle.Position;
-                       return go.CacheEnabled ?
-                               r + Parent.ClientRectangle.Position :
-                               Parent.ContextCoordinates (r);
-               }
-               public virtual Rectangle ScreenCoordinates (Rectangle r){
-                       try {
-                               return
-                                       Parent.ScreenCoordinates(r) + Parent.getSlot().Position + Parent.ClientRectangle.Position;                              
-                       } catch (Exception ex) {
-                               Debug.WriteLine (ex);
-                               return default(Rectangle);
-                       }
-               }
-               public virtual Rectangle getSlot () { return Slot;}
-               #endregion
-               public Point ScreenPointToLocal(Point p){
-                       Point pt = p - ScreenCoordinates (Slot).TopLeft - ClientRectangle.TopLeft;
-                       if (pt.X < 0)
-                               pt.X = 0;
-                       if (pt.Y < 0)
-                               pt.Y = 0;
-                       return pt;
-               }
-
-               #region EVENT HANDLERS
-               /// <summary>Occurs when mouse wheel is rolled in this object. It bubbles to the root</summary>
-               public event EventHandler<MouseWheelEventArgs> MouseWheelChanged;
-               /// <summary>Occurs when mouse button is released in this object. It bubbles to the root</summary>
-               public event EventHandler<MouseButtonEventArgs> MouseUp;
-               /// <summary>Occurs when mouse button is pressed in this object. It bubbles to the root</summary>
-               public event EventHandler<MouseButtonEventArgs> MouseDown;
-               /// <summary>Occurs when mouse button has been pressed then relesed in this object. It bubbles to the root</summary>
-               public event EventHandler<MouseButtonEventArgs> MouseClick;
-               /// <summary>Occurs when mouse button has been pressed then relesed 2 times in this object. It bubbles to the root</summary>
-               public event EventHandler<MouseButtonEventArgs> MouseDoubleClick;
-               /// <summary>Occurs when mouse mouve in this object. It bubbles to the root</summary>
-               public event EventHandler<MouseMoveEventArgs> MouseMove;
-               /// <summary>Occurs when mouse enter this object</summary>
-               public event EventHandler<MouseMoveEventArgs> MouseEnter;
-               /// <summary>Occurs when mouse leave this object</summary>
-               public event EventHandler<MouseMoveEventArgs> MouseLeave;
-               /// <summary>Occurs when key is pressed when this object is active</summary>
-               public event EventHandler<KeyEventArgs> KeyDown;
-               /// <summary>Occurs when key is released when this object is active</summary>
-               public event EventHandler<KeyEventArgs> KeyUp;
-               /// <summary>Occurs when translated key event occurs in the host when this object is active</summary>
-               public event EventHandler<KeyPressEventArgs> KeyPress;
-               /// <summary>Occurs when this object received focus</summary>
-               public event EventHandler Focused;
-               /// <summary>Occurs when this object loose focus</summary>
-               public event EventHandler Unfocused;
-               /// <summary>Occurs when mouse is over</summary>
-               public event EventHandler Hover;
-               /// <summary>Occurs when this control is no longer the Hover one</summary>
-               //public event EventHandler UnHover;
-               /// <summary>Occurs when this object loose focus</summary>
-               public event EventHandler Enabled;
-               /// <summary>Occurs when the enabled state this object is set to false</summary>
-               public event EventHandler Disabled;
-
-               #region DragAndDrop Events
-               public event EventHandler<DragDropEventArgs> StartDrag;
-               public event EventHandler<DragDropEventArgs> DragEnter;
-               public event EventHandler<DragDropEventArgs> DragLeave;
-               public event EventHandler<DragDropEventArgs> EndDrag;
-               public event EventHandler<DragDropEventArgs> Drop;
-               #endregion
-
-               /// <summary>
-               /// Occurs when default value and styling are loaded, and for templated control,
-               /// template is also loaded. Bindings should be functionnal as well.
-               /// </summary>
-               public event EventHandler Initialized;
-
-               /// <summary>Occurs when one part of the rendering slot changed</summary>
-               public event EventHandler<LayoutingEventArgs> LayoutChanged;
-               /// <summary>Occurs when DataSource changed</summary>
-               public event EventHandler<DataSourceChangeEventArgs> DataSourceChanged;
-               /// <summary>Occurs when the parent has changed</summary>
-               public event EventHandler<DataSourceChangeEventArgs> ParentChanged;
-               /// <summary>Occurs when the logical parent has changed</summary>
-               public event EventHandler<DataSourceChangeEventArgs> LogicalParentChanged;
-               #endregion
-
-               internal bool hasDoubleClick => MouseDoubleClick != null;
-               internal bool hasClick => MouseClick != null;
-
-               #region public properties
-               /// <summary>Random value placeholder</summary>
-               [DesignCategory ("Divers")]
-               public object Tag {
-                       get { return tag; }
-                       set {
-                               if (tag == value)
-                                       return;
-                               tag = value;
-                               NotifyValueChanged ("Tag", tag);
-                       }
-               }
-               /// <summary>
-               /// If enabled, resulting bitmap of graphic object is cached
-               /// speeding up rendering of complex object. Default is enabled.
-               /// </summary>
-               [DesignCategory ("Behavior")][DefaultValue(true)]
-               public virtual bool CacheEnabled {
-                       get { return cacheEnabled; }
-                       set {
-                               if (cacheEnabled == value)
-                                       return;
-                               cacheEnabled = value;
-                               NotifyValueChanged ("CacheEnabled", cacheEnabled);
-                       }
-               }
-               /// <summary>
-               /// If true, rendering of GraphicObject is clipped inside client rectangle
-               /// </summary>
-               [DesignCategory ("Appearance")][DefaultValue(true)]
-               public virtual bool ClipToClientRect {
-                       get { return clipToClientRect; }
-                       set {
-                               if (clipToClientRect == value)
-                                       return;
-                               clipToClientRect = value;
-                               NotifyValueChanged ("ClipToClientRect", clipToClientRect);
-                               this.RegisterForRedraw ();
-                       }
-               }
-               #if DEBUG_LOG
-               [XmlIgnore]public string TreePath {
-                       get { return this.GetType().Name + GraphicObjects.IndexOf(this).ToString ();    }
-               }
-               #endif
-               /// <summary>
-               /// Name is used in binding to reference other GraphicObjects inside the graphic tree
-               /// and by template controls to find special element in their template implementation such
-               /// as a container or a group to put children in.
-               /// </summary>
-               [DesignCategory ("Divers")][DefaultValue(null)]
-               public virtual string Name {
-                       get {
-                               #if DEBUG_LOG
-                               return string.IsNullOrEmpty(name) ? this.GetType().Name + GraphicObjects.IndexOf(this).ToString () : name;
-                               #else
-                               return name;
-                               #endif
-                       }
-                       set {
-                               if (name == value)
-                                       return;
-                               name = value;
-                               NotifyValueChanged("Name", name);
-                       }
-               }
-               /// <summary>
-               /// Vertical alignment inside parent, disabled if height is stretched
-               /// or top coordinate is not null
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue(VerticalAlignment.Center)]
-               public virtual VerticalAlignment VerticalAlignment {
-                       get { return verticalAlignment; }
-                       set {
-                               if (verticalAlignment == value)
-                                       return;
-
-                               verticalAlignment = value;
-                               NotifyValueChanged("VerticalAlignment", verticalAlignment);
-                               RegisterForLayouting (LayoutingType.Y);
-                       }
-               }
-               /// <summary>
-               /// Horizontal alignment inside parent, disabled if width is stretched
-               /// or left coordinate is not null
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue(HorizontalAlignment.Center)]
-               public virtual HorizontalAlignment HorizontalAlignment {
-                       get { return horizontalAlignment; }
-                       set {
-                               if (horizontalAlignment == value)
-                                       return;
-                               horizontalAlignment = value;
-                               NotifyValueChanged("HorizontalAlignment", horizontalAlignment);
-                               RegisterForLayouting (LayoutingType.X);
-                       }
-               }
-               /// <summary>
-               /// x position inside parent
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue(0)]
-               public virtual int Left {
-                       get { return left; }
-                       set {
-                               if (left == value)
-                                       return;
-                               left = value;
-                               NotifyValueChanged ("Left", left);
-                               this.RegisterForLayouting (LayoutingType.X);
-                       }
-               }
-               /// <summary>
-               /// y position inside parent
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue(0)]
-               public virtual int Top {
-                       get { return top; }
-                       set {
-                               if (top == value)
-                                       return;
-                               top = value;
-                               NotifyValueChanged ("Top", top);
-                               this.RegisterForLayouting (LayoutingType.Y);
-                       }
-               }
-               /// <summary>
-               /// Helper property used to set width and height to fit in one call
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue(false)]
-               public virtual bool Fit {
-                       get { return Width == Measure.Fit && Height == Measure.Fit ? true : false; }
-                       set {
-                               if (value == Fit)
-                                       return;
-
-                               Width = Height = Measure.Fit;
-                       }
-               }
-               /// <summary>
-               /// Width of this control, by default inherited from parent. May have special values
-               /// such as Stretched or Fit. It may be proportionnal or absolute.
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue("Inherit")]
-               public virtual Measure Width {
-                       get {
-                               return width.Units == Unit.Inherit ?
-                                       Parent is Widget ? (Parent as Widget).WidthPolicy :
-                                       Measure.Stretched : width;
-                       }
-                       set {
-                               if (width == value)
-                                       return;
-                               if (value.IsFixed) {
-                                       if (value < minimumSize.Width || (value > maximumSize.Width && maximumSize.Width > 0))
-                                               return;
-                               }
-                               Measure old = width;
-                               width = value;
-                               NotifyValueChanged ("Width", width);
-                               if (width == Measure.Stretched || old == Measure.Stretched) {
-                                       //NotifyValueChanged ("WidthPolicy", width.Policy);
-                                       //contentSize in Stacks are only update on childLayoutChange, and the single stretched
-                                       //child of the stack is not counted in contentSize, so when changing size policy of a child
-                                       //we should adapt contentSize
-                                       //TODO:check case when child become stretched, and another stretched item already exists.
-                                       GenericStack gs = Parent as GenericStack;
-                                       if (gs != null){ //TODO:check if I should test Group instead
-                                               if (gs.Orientation == Orientation.Horizontal) {
-                                                       if (width == Measure.Stretched)
-                                                               gs.contentSize.Width -= this.LastSlots.Width;
-                                                       else
-                                                               gs.contentSize.Width += this.LastSlots.Width;
-                                               }
-                                       }                                                       
-                               }
-
-                               this.RegisterForLayouting (LayoutingType.Width);
-                       }
-               }
-               /// <summary>
-               /// Height of this control, by default inherited from parent. May have special values
-               /// such as Stretched or Fit. It may be proportionnal or absolute.
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue("Inherit")]
-               public virtual Measure Height {
-                       get {
-                               return height.Units == Unit.Inherit ?
-                                       Parent is Widget ? (Parent as Widget).HeightPolicy :
-                                       Measure.Stretched : height;
-                       }
-                       set {
-                               if (height == value)
-                                       return;
-                               if (value.IsFixed) {
-                                       if (value < minimumSize.Height || (value > maximumSize.Height && maximumSize.Height > 0))
-                                               return;
-                               }
-                               Measure old = height;
-                               height = value;
-                               NotifyValueChanged ("Height", height);
-                               if (height == Measure.Stretched || old == Measure.Stretched) {
-                                       //NotifyValueChanged ("HeightPolicy", HeightPolicy);
-                                       GenericStack gs = Parent as GenericStack;
-                                       if (gs != null){ //TODO:check if I should test Group instead
-                                               if (gs.Orientation == Orientation.Vertical) {
-                                                       if (height == Measure.Stretched)
-                                                               gs.contentSize.Height -= this.LastSlots.Height;
-                                                       else
-                                                               gs.contentSize.Height += this.LastSlots.Height;
-                                               }
-                                       }
-                               }
-
-                               this.RegisterForLayouting (LayoutingType.Height);
-                       }
-               }
-               /// <summary>
-               /// Was Used for binding on dimensions, this property will never hold fixed size, but instead only
-               /// Fit or Stretched, **with inherited state implementation, it is not longer used in binding**
-               /// </summary>
-               [XmlIgnore]public virtual Measure WidthPolicy { get {
-                               return Width.IsFit ? Measure.Fit : Measure.Stretched; } }
-               /// <summary>
-               /// Was Used for binding on dimensions, this property will never hold fixed size, but instead only
-               /// Fit or Stretched, **with inherited state implementation, it is not longer used in binding**
-               /// </summary>
-               [XmlIgnore]public virtual Measure HeightPolicy { get {
-                               return Height.IsFit ? Measure.Fit : Measure.Stretched; } }
-               /// <summary>
-               /// Indicate that this object may received focus or not, if not focusable all the descendants are 
-               /// affected.
-               /// </summary>
-               [DesignCategory ("Behaviour")][DefaultValue(false)]
-               public virtual bool Focusable {
-                       get { return focusable; }
-                       set {
-                               if (focusable == value)
-                                       return;
-                               focusable = value;
-                               NotifyValueChanged ("Focusable", focusable);
-                       }
-               }
-               /// <summary>
-               /// True when this control has the focus, only one control per interface may have it.
-               /// </summary>
-               [XmlIgnore]public virtual bool HasFocus {
-                       get { return hasFocus; }
-                       set {
-                               if (value == hasFocus)
-                                       return;
-
-                               hasFocus = value;
-                               if (hasFocus)
-                                       onFocused (this, null);
-                               else
-                                       onUnfocused (this, null);
-                               NotifyValueChanged ("HasFocus", hasFocus);
-                       }
-               }
-               /// <summary>
-               /// true if this control is active, this means that mouse has been pressed in it and not yet released. It could 
-               /// be used for other two states periferic action.
-               /// </summary>
-               [XmlIgnore]public virtual bool IsActive {
-                       get { return isActive; }
-                       set {
-                               if (value == isActive)
-                                       return;
-
-                               isActive = value;
-                               NotifyValueChanged ("IsActive", isActive);
-                       }
-               }
-               /// <summary>
-               /// true if this control has the pointer hover
-               /// </summary>
-               [XmlIgnore]public virtual bool IsHover {
-                       get { return isHover; }
-                       set {
-                               if (value == isHover)
-                                       return;
-
-                               isHover = value;
-
-                               if (isHover)
-                                       Hover.Raise (this, null);
-
-                               NotifyValueChanged ("IsHover", isHover);
-                       }
-               }
-               /// <summary>
-               /// true if holding mouse button down should trigger multiple click events
-               /// </summary>
-               [DesignCategory ("Behaviour")][DefaultValue(false)]
-               public virtual bool MouseRepeat {
-                       get { return mouseRepeat; }
-                       set {
-                               if (mouseRepeat == value)
-                                       return;
-                               mouseRepeat = value;
-                               NotifyValueChanged ("MouseRepeat", mouseRepeat);
-                       }
-               }
-               /// <summary>
-               /// Determine Cursor when mouse is Hover.
-               /// </summary>
-               [DesignCategory ("Behaviour")]
-               [DefaultValue (MouseCursor.Arrow)]
-               public virtual MouseCursor MouseCursor {
-                       get { return mouseCursor; }
-                       set {
-                               if (mouseCursor == value)
-                                       return;
-                               mouseCursor = value;
-                               NotifyValueChanged ("MouseCursor", mouseCursor);
-                               this.RegisterForRedraw ();
-
-                               if (isHover)
-                                       IFace.MouseCursor = mouseCursor;
-                       }
-               }
-
-               /// <summary>
-               /// forward mouse events even if an handle is bound
-               /// </summary>
-               //[DesignCategory ("Behaviour")][DefaultValue (false)]
-               //public bool ForwardMouseEvents {
-               //      get { return forwardMouseEvents; }
-               //      set {
-               //              if (forwardMouseEvents == value)
-               //                      return;
-               //              forwardMouseEvents = value;
-               //              NotifyValueChanged ("ForwardMouseEvents", forwardMouseEvents);
-               //      }
-               //}
-               bool clearBackground = false;
-               /// <summary>
-               /// background fill of the control, maybe solid color, gradient, image, or svg
-               /// </summary>
-               [DesignCategory ("Appearance")][DefaultValue("Transparent")]
-               public virtual Fill Background {
-                       get { return background; }
-                       set {
-                               if (background == value)
-                                       return;
-                               clearBackground = false;
-                               if (value == null)
-                                       return;
-                               background = value;
-                               NotifyValueChanged ("Background", background);
-                               RegisterForRedraw ();
-                               if (background is SolidColor) {
-                                       if ((background as SolidColor).Equals (Color.Clear))
-                                               clearBackground = true;
-                               }
-                       }
-               }
-               /// <summary>
-               /// Foreground fill of the control, usage may be different among derived controls
-               /// </summary>
-               [DesignCategory ("Appearance")][DefaultValue("White")]
-               public virtual Fill Foreground {
-                       get { return foreground; }
-                       set {
-                               if (foreground == value)
-                                       return;
-                               foreground = value;
-                               NotifyValueChanged ("Foreground", foreground);
-                               RegisterForRedraw ();
-                       }
-               }
-               /// <summary>
-               /// Font being used in many controls, it is defined in the base GraphicObject class.
-               /// </summary>
-               [DesignCategory ("Appearance")][DefaultValue("sans, 10")]
-               public virtual Font Font {
-                       get { return font; }
-                       set {
-                               if (value == font)
-                                       return;
-                               font = value;
-                               NotifyValueChanged ("Font", font);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary>
-               /// to get rounded corners
-               /// </summary>
-               [DesignCategory ("Appearance")][DefaultValue(0.0)]
-               public virtual double CornerRadius {
-                       get { return cornerRadius; }
-                       set {
-                               if (value == cornerRadius)
-                                       return;
-                               cornerRadius = value;
-                               NotifyValueChanged ("CornerRadius", cornerRadius);
-                               RegisterForRedraw ();
-                       }
-               }
-               /// <summary>
-               /// This is a single integer for the 4 direction, a gap between the control and it's container,
-               /// by default it is filled with the background.
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue(0)]
-               public virtual int Margin {
-                       get { return margin; }
-                       set {
-                               if (value == margin)
-                                       return;
-                               margin = value;
-                               NotifyValueChanged ("Margin", margin);
-                               RegisterForGraphicUpdate ();
-                       }
-               }
-               /// <summary>
-               /// set the visible state of the control, invisible controls does reserve space in the layouting system.
-               /// </summary>
-               [DesignCategory ("Appearance")][DefaultValue(true)]
-               public virtual bool Visible {
-                       get { return isVisible; }
-                       set {
-                               if (value == isVisible)
-                                       return;
-
-                               isVisible = value;
-
-                               RegisterForLayouting (LayoutingType.Sizing);
-
-                               if (!isVisible && IFace.HoverWidget != null) {                                  
-                                       if (IFace.HoverWidget.IsOrIsInside (this)) {
-                                               //IFace.HoverWidget = null;
-                                               IFace.OnMouseMove (IFace.Mouse.X, IFace.Mouse.Y);
-                                       }
-                               }
-
-                               NotifyValueChanged ("Visible", isVisible);
-                       }
-               }
-               /// <summary>
-               /// get or set the enabled state, disabling a control will affect focuability and
-               /// also it's rendering which will be grayed
-               /// </summary>
-               [DesignCategory ("Behaviour")][DefaultValue(true)]
-               public virtual bool IsEnabled {
-                       get { return isEnabled; }
-                       set {
-                               if (value == isEnabled)
-                                       return;
-
-                               isEnabled = value;
-
-                               if (isEnabled)
-                                       onEnable (this, null);
-                               else
-                                       onDisable (this, null);
-
-                               NotifyValueChanged ("IsEnabled", isEnabled);
-                               RegisterForRedraw ();
-                       }
-               }
-               /// <summary>
-               /// Minimal width and  height for this control
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue("1,1")]
-               public virtual Size MinimumSize {
-                       get { return minimumSize; }
-                       set {
-                               if (value == minimumSize)
-                                       return;
-
-                               minimumSize = value;
-
-                               NotifyValueChanged ("MinimumSize", minimumSize);
-                               RegisterForLayouting (LayoutingType.Sizing);
-                       }
-               }
-               /// <summary>
-               /// Maximum width and  height for this control, unlimited if null.
-               /// </summary>
-               [DesignCategory ("Layout")][DefaultValue("0,0")]
-               public virtual Size MaximumSize {
-                       get { return maximumSize; }
-                       set {
-                               if (value == maximumSize)
-                                       return;
-
-                               maximumSize = value;
-
-                               NotifyValueChanged (nameof(MaximumSize), maximumSize);
-                               RegisterForLayouting (LayoutingType.Sizing);
-                       }
-               }
-               /// <summary>
-               /// Fully qualify type name of expected data source.
-               /// If set, datasource bindings will be speedup by avoiding reflexion in generated dyn methods.
-               /// If an object of a different type is set as datasource, bindings will be canceled.
-               /// It accepts all derived type.
-               /// </summary>
-               [DesignCategory ("Data")]
-               public Type DataSourceType {
-                       get { return dataSourceType; }
-                       set { dataSourceType = value; }
-               }
-               /// <summary>
-               /// Seek first logical tree upward if logicalParent is set, or seek graphic tree for
-               /// a not null dataSource that will be active for all descendants having dataSource=null
-               /// </summary>
-               [DesignCategory ("Data")]
-               public virtual object DataSource {
-                       set {
-                               if (DataSource == value)
-                                       return;
-
-                               DataSourceChangeEventArgs dse = new DataSourceChangeEventArgs (DataSource, null);
-                               dataSource = value;
-                               dse.NewDataSource = DataSource;
-
-                               if (dse.NewDataSource == dse.OldDataSource)
-                                       return;
-
-                               if (value != null)
-                                       rootDataLevel = true;
-
-                               #if DEBUG_LOG
-                               DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOLockLayouting, this);
-                               #endif
-                               lock (IFace.UpdateMutex) {
-                                       OnDataSourceChanged (this, dse);
-                                       NotifyValueChanged ("DataSource", DataSource);
-                               }
-                               #if DEBUG_LOG
-                               dbgEvt.end = DebugLog.chrono.ElapsedTicks;
-                               #endif
-                       }
-                       get {
-                               return rootDataLevel ? dataSource : dataSource == null ?
-                                       LogicalParent == null ? null :
-                                       LogicalParent is Widget ? (LogicalParent as Widget).DataSource : null :
-                                       dataSource;
-                       }
-               }
-               /// <summary>
-               /// If true, lock datasource seeking upward in logic or graphic tree to this widget
-               /// </summary>
-               [DesignCategory ("Data")][DefaultValue(false)]
-               public virtual bool RootDataLevel {
-                       get { return rootDataLevel; }
-                       set {
-                               if (rootDataLevel == value)
-                                       return;
-                               rootDataLevel = value;
-                               NotifyValueChanged ("RootDataLevel", rootDataLevel);
-                               this.RegisterForRedraw ();
-                       }
-               }
-               protected virtual void onLogicalParentDataSourceChanged(object sender, DataSourceChangeEventArgs e){
-                       if (localDataSourceIsNull)
-                               OnDataSourceChanged (this, e);
-               }
-               internal bool localDataSourceIsNull { get { return dataSource == null; } }
-               public bool localLogicalParentIsNull { get { return logicalParent == null; } }
-
-               public virtual void OnDataSourceChanged(object sender, DataSourceChangeEventArgs e){
-                       DataSourceChanged.Raise (this, e);
-                       #if DEBUG_LOG
-                       DebugLog.AddEvent(DbgEvtType.GONewDataSource, this);
-                       #endif
-
-                       #if DEBUG_BINDING
-                       Debug.WriteLine("New DataSource for => {0} \n\t{1}=>{2}", this.ToString(),e.OldDataSource,e.NewDataSource);
-                       #endif
-               }
-               /// <summary>
-               /// Style key to use for this control
-               /// </summary>
-               [DesignCategory ("Appearance")]
-               public virtual string Style {
-                       get { return style; }
-                       set {
-                               if (value == style)
-                                       return;
-
-                               style = value;
-
-                               NotifyValueChanged ("Style", style);
-                       }
-               }
-               [DesignCategory ("Divers")]
-               public virtual string Tooltip {
-                       get { return tooltip; }
-                       set {
-                               if (tooltip == value)
-                                       return;
-                               tooltip = value;
-                               NotifyValueChanged("Tooltip", tooltip);
-                       }
-               }
-               [DesignCategory ("Divers")]
-               public IList<Command> ContextCommands {
-                       get { return contextCommands; }
-                       set {
-                               if (contextCommands == value)
-                                       return;
-                               contextCommands = value;
-                               NotifyValueChanged("ContextCommands", contextCommands);
-                       }
-               }
-               #endregion
-
-               #region Default and Style Values loading
-               /// <summary> Loads the default values from XML attributes default </summary>
-               public void loadDefaultValues()
-               {
-                       #if DEBUG_LOG
-                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOInitialization, this);
-                       #endif
-
-                       Type thisType = this.GetType ();
-
-                       if (!string.IsNullOrEmpty (style)) {
-                               if (IFace.DefaultValuesLoader.ContainsKey (style)) {
-                                       IFace.DefaultValuesLoader [style] (this);
-                                       onInitialized (this, null);
-                                       return;
-                               }
-                       } else if (IFace.DefaultValuesLoader.ContainsKey (thisType.FullName)) {
-                               IFace.DefaultValuesLoader [thisType.FullName] (this);
-                               onInitialized (this, null);
-                               return;
-                       } else  if (IFace.DefaultValuesLoader.ContainsKey (thisType.Name)) {
-                               IFace.DefaultValuesLoader [thisType.Name] (this);
-                               onInitialized (this, null);
-                               return;
-                       }
-
-                       List<Style> styling = new List<Style>();
-
-                       //Search for a style matching :
-                       //1: Full class name, with full namespace
-                       //2: class name
-                       //3: style may have been registered with their ressource ID minus .style extention
-                       //   those files being placed in a Styles folder
-                       string styleKey = style;
-                       if (!string.IsNullOrEmpty (style)) {
-                               if (IFace.Styling.ContainsKey (style)) {
-                                       styling.Add (IFace.Styling [style]);
-                               }
-                       }
-                       if (IFace.Styling.ContainsKey (thisType.FullName)) {
-                               styling.Add (IFace.Styling [thisType.FullName]);
-                               if (string.IsNullOrEmpty (styleKey))
-                                       styleKey = thisType.FullName;
-                       }
-                       if (IFace.Styling.ContainsKey (thisType.Name)) {
-                               styling.Add (IFace.Styling [thisType.Name]);
-                               if (string.IsNullOrEmpty (styleKey))
-                                       styleKey = thisType.Name;
-                       }
-
-                       if (string.IsNullOrEmpty (styleKey))
-                               styleKey = thisType.FullName;
-
-                       //Reflexion being very slow compared to dyn method or delegates,
-                       //I compile the initial values coded in the CustomAttribs of the class,
-                       //all other instance of this type would not longer use reflexion to init properly
-                       //but will fetch the  dynamic initialisation method compiled for this precise type
-                       //TODO:measure speed gain.
-#region Delfault values Loading dynamic compilation
-                       DynamicMethod dm = null;
-                       ILGenerator il = null;
-
-                       dm = new DynamicMethod("dyn_loadDefValues", null, new Type[] { typeof (object) }, thisType, true);
-
-            il = dm.GetILGenerator(256);
-                       il.DeclareLocal(typeof (object));//store root
-                       il.Emit(OpCodes.Nop);
-                       //set local GraphicObject to root object passed as 1st argument
-                       il.Emit (OpCodes.Ldarg_0);
-                       il.Emit (OpCodes.Stloc_0);
-
-                       foreach (EventInfo ei in thisType.GetEvents(BindingFlags.Public | BindingFlags.Instance)) {
-                               string expression;
-                               if (!getDefaultEvent(ei, styling, out expression))
-                                       continue;
-                               //TODO:dynEventHandler could be cached somewhere, maybe a style instanciator class holding the styling delegate and bound to it.
-                               foreach (string exp in CompilerServices.splitOnSemiColumnOutsideAccolades(expression)) {
-                                       string trimed = exp.Trim();
-                                       if (trimed.StartsWith ("{", StringComparison.Ordinal)){
-                                               il.Emit (OpCodes.Ldloc_0);//load this as 1st arg of event Add
-
-                                               //push eventInfo as 1st arg of compile
-                                               il.Emit (OpCodes.Ldloc_0);
-                                               il.Emit (OpCodes.Call, CompilerServices.miGetType);
-                                               il.Emit (OpCodes.Ldstr, ei.Name);//push event name
-                                               il.Emit (OpCodes.Call, CompilerServices.miGetEvent);
-                                               //push expression as 2nd arg of compile
-                                               il.Emit (OpCodes.Ldstr, trimed.Substring (1, trimed.Length - 2));
-                                               //push null as 3rd arg, currentNode, not known when instanciing
-                                               il.Emit (OpCodes.Ldnull);
-                                               il.Emit (OpCodes.Call, CompilerServices.miCompileDynEventHandler);
-                                               il.Emit (OpCodes.Castclass, ei.EventHandlerType);
-                                               il.Emit (OpCodes.Callvirt, ei.AddMethod);
-                                       }else
-                                               Debug.WriteLine("error in styling, event not handled : " + trimed);
-                               }
-                       }
-
-                       foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
-                               if (pi.GetSetMethod () == null)
-                                       continue;
-                               XmlIgnoreAttribute xia = (XmlIgnoreAttribute)pi.GetCustomAttribute (typeof(XmlIgnoreAttribute));
-                               if (xia != null)
-                                       continue;
-
-                               object defaultValue;
-
-                               int styleIndex = -1;
-                               if (styling.Count > 0){
-                                       for (int i = 0; i < styling.Count; i++) {
-                                               if (styling[i].ContainsKey (pi.Name)){
-                                                       styleIndex = i;
-                                                       break;
-                                               }
-                                       }
-                               }
-                               if (styleIndex >= 0){
-                                       if (pi.PropertyType.IsEnum)//maybe should be in parser..
-                                               defaultValue = Enum.Parse(pi.PropertyType, (string)styling[styleIndex] [pi.Name], true);
-                                       else
-                                               defaultValue = styling[styleIndex] [pi.Name];
-
-                                       #if DESIGN_MODE
-                                       if (defaultValue != null){
-                                               FileLocation fl = styling[styleIndex].Locations[pi.Name];
-                                               il.Emit (OpCodes.Ldloc_0);
-                                               il.Emit (OpCodes.Ldstr, pi.Name);
-                                               il.Emit (OpCodes.Ldstr, fl.FilePath);
-                                               il.Emit (OpCodes.Ldc_I4, fl.Line);
-                                               il.Emit (OpCodes.Ldc_I4, fl.Column);
-                                               il.Emit (OpCodes.Call, miDesignAddDefLoc);
-
-                                               il.Emit (OpCodes.Ldloc_0);
-                                               il.Emit (OpCodes.Ldfld, typeof(Widget).GetField("design_style_values"));
-                                               il.Emit (OpCodes.Ldstr, pi.Name);
-                                               il.Emit (OpCodes.Ldstr, defaultValue.ToString());
-                                               il.Emit (OpCodes.Call, CompilerServices.miDicStrStrAdd);
-                                       }
-                                       #endif
-
-                               }else {
-                                       DefaultValueAttribute dv = (DefaultValueAttribute)pi.GetCustomAttribute (typeof (DefaultValueAttribute));
-                                       if (dv == null)
-                                               continue;
-                                       defaultValue = dv.Value;
-                               }
-
-                               CompilerServices.EmitSetValue (il, pi, defaultValue);
-                       }
-                       il.Emit(OpCodes.Ret);
-                       #endregion
-
-                       try {
-                               IFace.DefaultValuesLoader[styleKey] = (Interface.LoaderInvoker)dm.CreateDelegate(typeof(Interface.LoaderInvoker));
-                               IFace.DefaultValuesLoader[styleKey] (this);
-                       } catch (Exception ex) {
-                               throw new Exception ("Error applying style <" + styleKey + ">:", ex);
-                       }
-
-                       #if DEBUG_LOG
-                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
-                       #endif
-
-                       onInitialized (this, null);
-               }
-               protected virtual void onInitialized (object sender, EventArgs e){
-                       Initialized.Raise(sender, e);
-               }
-               bool getDefaultEvent(EventInfo ei, List<Style> styling,
-                       out string expression){
-                       expression = "";
-                       if (styling.Count > 0){
-                               for (int i = 0; i < styling.Count; i++) {
-                                       if (styling[i].ContainsKey (ei.Name)){
-                                               expression = (string)styling[i] [ei.Name];
-                                               return true;
-                                       }
-                               }
-                       }
-                       return false;
-               }
-#endregion
-
-               public virtual Widget FindByName(string nameToFind){
-                       return string.Equals(nameToFind, name, StringComparison.Ordinal) ? this : null;
-               }
-               public virtual bool Contains(Widget goToFind){
-                       return false;
-               }
-               /// <summary>
-               /// return true if this is contained inside go
-               /// </summary>
-               public bool IsOrIsInside(Widget go){
-                       if (this == go)
-                               return true;
-                       ILayoutable p = this.Parent;
-                       while (p != null) {
-                               if (p == go)
-                                       return true;
-                               p = p.Parent;
-                       }
-                       return false;
-               }
-
-               #region Drag&Drop
-               [DesignCategory ("DragAndDrop")][DefaultValue(false)]
-               public virtual bool AllowDrag {
-                       get { return allowDrag; }
-                       set {
-                               if (allowDrag == value)
-                                       return;
-                               allowDrag = value;
-                               NotifyValueChanged ("AllowDrag", allowDrag);
-                       }
-               }
-               [DesignCategory ("DragAndDrop")][DefaultValue(false)]
-               public virtual bool AllowDrop {
-                       get { return allowDrop; }
-                       set {
-                               if (allowDrop == value)
-                                       return;
-                               allowDrop = value;
-                               NotifyValueChanged ("AllowDrop", allowDrop);
-                       }
-               }
-
-//             public List<Type> AllowedDroppedTypes;
-//             public void AddAllowedDroppedType (Type newType){
-//                     if (AllowedDroppedTypes == null)
-//                             AllowedDroppedTypes = new List<Type> ();
-//                     AllowedDroppedTypes.Add (newType);
-//                     NotifyValueChanged ("AllowDrop", AllowDrop);
-//             }
-//             [XmlIgnore]public virtual bool AllowDrop {
-//                     get { return AllowedDroppedTypes?.Count>0; }
-//             }
-               [XmlIgnore]public virtual bool IsDragged {
-                       get { return isDragged; }
-                       set {
-                               if (isDragged == value)
-                                       return;
-                               isDragged = value;
-
-                               NotifyValueChanged ("IsDragged", IsDragged);
-                       }
-               }
-               /// <summary>
-               /// fired when drag and drop operation start
-               /// </summary>
-               protected virtual void onStartDrag (object sender, DragDropEventArgs e){
-                       IFace.HoverWidget = null;
-                       IsDragged = true;
-                       StartDrag.Raise (this, e);
-                       #if DEBUG_DRAGNDROP
-                       Debug.WriteLine(this.ToString() + " : START DRAG => " + e.ToString());
-                       #endif
-               }
-               /// <summary>
-               ///  Occured when dragging ends without dropping
-               /// </summary>
-               protected virtual void onEndDrag (object sender, DragDropEventArgs e){                  
-                       IsDragged = false;
-                       EndDrag.Raise (this, e);
-                       #if DEBUG_DRAGNDROP
-                       Debug.WriteLine(this.ToString() + " : END DRAG => " + e.ToString());
-                       #endif
-               }
-               protected virtual void onDragEnter (object sender, DragDropEventArgs e){
-                       e.DropTarget = this;
-                       DragEnter.Raise (this, e);
-                       #if DEBUG_DRAGNDROP
-                       Debug.WriteLine(this.ToString() + " : DRAG Enter => " + e.ToString());
-                       #endif
-               }
-               protected virtual void onDragLeave (object sender, DragDropEventArgs e){                        
-                       e.DropTarget = null;
-                       DragLeave.Raise (this, e);
-                       #if DEBUG_DRAGNDROP
-                       Debug.WriteLine(this.ToString() + " : DRAG Leave => " + e.ToString());
-                       #endif
-               }
-               protected virtual void onDrop (object sender, DragDropEventArgs e){                     
-                       IsDragged = false;
-                       Drop.Raise (this, e);
-                       //e.DropTarget.onDragLeave (this, e);//raise drag leave in target
-                       #if DEBUG_DRAGNDROP
-                       Debug.WriteLine(this.ToString() + " : DROP => " + e.ToString());
-                       #endif
-               }
-               public bool IsDropTarget {
-                       get { return IFace.DragAndDropOperation?.DropTarget == this; }
-               }
-
-               #endregion
-
-               #region Queuing
-               /// <summary>
-               /// Register old and new slot for clipping
-               /// </summary>
-               public virtual void ClippingRegistration(){
-                       #if DEBUG_LOG
-                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOClippingRegistration, this);
-                       #endif  
-                       parentRWLock.EnterReadLock ();
-                       if (parent != null) {                                   
-                               Parent.RegisterClip (LastPaintedSlot);
-                               Parent.RegisterClip (Slot);
-                       }
-                       parentRWLock.ExitReadLock ();
-                       #if DEBUG_LOG
-                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
-                       #endif
-               }
-               /// <summary>
-               /// Add clip rectangle to this.clipping and propagate up to root
-               /// </summary>
-               /// <param name="clip">Clip rectangle</param>
-               public virtual void RegisterClip(Rectangle clip){
-                       #if DEBUG_LOG
-                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GORegisterClip, this);
-                       #endif
-                       Rectangle cb = ClientRectangle;
-                       Rectangle  r = clip + cb.Position;
-                       if (r.Right > cb.Right)
-                               r.Width -= r.Right - cb.Right;
-                       if (r.Bottom > cb.Bottom)
-                               r.Height -= r.Bottom - cb.Bottom;
-                       if (cacheEnabled && !IsDirty)
-                               Clipping.UnionRectangle (r);
-                       if (Parent == null)
-                               return;
-                       Widget p = Parent as Widget;
-                       if (p?.IsDirty == true && p?.CacheEnabled == true)
-                               return;
-                       Parent.RegisterClip (r + Slot.Position);
-                       #if DEBUG_LOG
-                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
-                       #endif
-               }
-               /// <summary> Full update, content and layouting, taking care of sizing policy </summary>
-               [MethodImpl(MethodImplOptions.AggressiveInlining)]
-               public void RegisterForGraphicUpdate ()
-               {
-                       IsDirty = true;
-                       if (Width.IsFit || Height.IsFit)
-                               RegisterForLayouting (LayoutingType.Sizing);
-                       else if (RegisteredLayoutings == LayoutingType.None)
-                               IFace.EnqueueForRepaint (this);
-               }
-               /// <summary> query an update of the content without layouting changes</summary>
-               [MethodImpl(MethodImplOptions.AggressiveInlining)]
-               public void RegisterForRedraw ()
-               {
-                       IsDirty = true;
-                       if (RegisteredLayoutings == LayoutingType.None)
-                               IFace.EnqueueForRepaint (this);
-               }
-               #endregion
-
-               #region Layouting
-
-               /// <summary> return size of content + margins </summary>
-               protected virtual int measureRawSize (LayoutingType lt) {
-                       return lt == LayoutingType.Width ?
-                               contentSize.Width + 2 * margin: contentSize.Height + 2 * margin;
-               }
-               /// <summary> By default in groups, LayoutingType.ArrangeChildren is reset </summary>
-               public virtual void ChildrenLayoutingConstraints(ref LayoutingType layoutType){
-               }
-               public virtual bool ArrangeChildren { get { return false; } }
-               public virtual void RegisterForLayouting(LayoutingType layoutType){
-                       if (Parent == null)
-                               return;
-                       lock (IFace.LayoutMutex) {
-                               //prevent queueing same LayoutingType for this
-                               layoutType &= (~RegisteredLayoutings);
-
-                               if (layoutType == LayoutingType.None)
-                                       return;
-                               //dont set position for stretched item
-                               if (Width == Measure.Stretched)
-                                       layoutType &= (~LayoutingType.X);
-                               if (Height == Measure.Stretched)
-                                       layoutType &= (~LayoutingType.Y);
-
-                               if (!ArrangeChildren)
-                                       layoutType &= (~LayoutingType.ArrangeChildren);
-
-                               //apply constraints depending on parent type
-                               if (Parent is Widget)
-                                       (Parent as Widget).ChildrenLayoutingConstraints (ref layoutType);
-
-//                             //prevent queueing same LayoutingType for this
-                               layoutType &= (~RegisteredLayoutings);
-
-                               if (layoutType == LayoutingType.None)
-                                       return;
-
-                               //enqueue LQI LayoutingTypes separately
-                               if (layoutType.HasFlag (LayoutingType.Width))
-                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Width, this));
-                               if (layoutType.HasFlag (LayoutingType.Height))
-                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Height, this));
-                               if (layoutType.HasFlag (LayoutingType.X))
-                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.X, this));
-                               if (layoutType.HasFlag (LayoutingType.Y))
-                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Y, this));
-                               if (layoutType.HasFlag (LayoutingType.ArrangeChildren))
-                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this));
-                       }
-               }
-
-               /// <summary> trigger dependant sizing component update </summary>
-               public virtual void OnLayoutChanges(LayoutingType  layoutType)
-               {
-                       switch (layoutType) {
-                       case LayoutingType.Width:
-                               RegisterForLayouting (LayoutingType.X);
-                               break;
-                       case LayoutingType.Height:
-                               RegisterForLayouting (LayoutingType.Y);
-                               break;
-                       }
-                       LayoutChanged.Raise (this, new LayoutingEventArgs (layoutType));
-               }
-               internal protected void raiseLayoutChanged(LayoutingEventArgs e){
-                       LayoutChanged.Raise (this, e);
-               }
-               /// <summary> Update layout component only one at a time, this is where the computation of alignement
-               /// and size take place.
-               /// The redrawing will only be triggered if final slot size has changed </summary>
-               /// <returns><c>true</c>, if layouting was possible, <c>false</c> if conditions were not
-               /// met and LQI has to be re-queued</returns>
-               public virtual bool UpdateLayout (LayoutingType layoutType)
-               {
-                       //unset bit, it would be reset if LQI is re-queued
-                       registeredLayoutings &= (~layoutType);
-
-                       switch (layoutType) {
-                       case LayoutingType.X:
-                               if (left == 0) {
-
-                                       if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width) ||
-                                           RegisteredLayoutings.HasFlag (LayoutingType.Width))
-                                               return false;
-
-                                       switch (horizontalAlignment) {
-                                       case HorizontalAlignment.Left:
-                                               Slot.X = 0;
-                                               break;
-                                       case HorizontalAlignment.Right:
-                                               Slot.X = Parent.ClientRectangle.Width - Slot.Width;
-                                               break;
-                                       case HorizontalAlignment.Center:
-                                               Slot.X = Parent.ClientRectangle.Width / 2 - Slot.Width / 2;
-                                               break;
-                                       }
-                               } else
-                                       Slot.X = left;
-
-                               if (LastSlots.X == Slot.X)
-                                       break;
-
-                               IsDirty = true;
-
-                               OnLayoutChanges (layoutType);
-
-                               LastSlots.X = Slot.X;
-                               break;
-                       case LayoutingType.Y:
-                               if (top == 0) {
-
-                                       if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height) ||
-                                           RegisteredLayoutings.HasFlag (LayoutingType.Height))
-                                               return false;
-
-                                       switch (verticalAlignment) {
-                                       case VerticalAlignment.Top://this could be processed even if parent Height is not known
-                                               Slot.Y = 0;
-                                               break;
-                                       case VerticalAlignment.Bottom:
-                                               Slot.Y = Parent.ClientRectangle.Height - Slot.Height;
-                                               break;
-                                       case VerticalAlignment.Center:
-                                               Slot.Y = Parent.ClientRectangle.Height / 2 - Slot.Height / 2;
-                                               break;
-                                       }
-                               } else
-                                       Slot.Y = top;
-
-                               if (LastSlots.Y == Slot.Y)
-                                       break;
-
-                               IsDirty = true;
-
-                               OnLayoutChanges (layoutType);
-
-                               LastSlots.Y = Slot.Y;
-                               break;
-                       case LayoutingType.Width:
-                               if (isVisible) {
-                                       if (Width.IsFixed)
-                                               Slot.Width = Width;
-                                       else if (Width == Measure.Fit) {
-                                               Slot.Width = measureRawSize (LayoutingType.Width);
-                                       } else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width))
-                                               return false;
-                                       else if (Width == Measure.Stretched)
-                                               Slot.Width = Parent.ClientRectangle.Width;
-                                       else
-                                               Slot.Width = (int)Math.Round ((double)(Parent.ClientRectangle.Width * Width) / 100.0);
-
-                                       if (Slot.Width < 0)
-                                               return false;
-
-                                       //size constrain
-                                       if (Slot.Width < minimumSize.Width) {
-                                               Slot.Width = minimumSize.Width;
-                                               //NotifyValueChanged ("WidthPolicy", Measure.Stretched);
-                                       } else if (Slot.Width > maximumSize.Width && maximumSize.Width > 0) {
-                                               Slot.Width = maximumSize.Width;
-                                               //NotifyValueChanged ("WidthPolicy", Measure.Stretched);
-                                       }
-                               } else
-                                       Slot.Width = 0;
-
-                               if (LastSlots.Width == Slot.Width)
-                                       break;
-
-                               IsDirty = true;
-
-                               OnLayoutChanges (layoutType);
-
-                               LastSlots.Width = Slot.Width;
-                               break;
-                       case LayoutingType.Height:
-                               if (isVisible) {
-                                       if (Height.IsFixed)
-                                               Slot.Height = Height;
-                                       else if (Height == Measure.Fit) {
-                                               Slot.Height = measureRawSize (LayoutingType.Height);
-                                       } else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height))
-                                               return false;
-                                       else if (Height == Measure.Stretched)
-                                               Slot.Height = Parent.ClientRectangle.Height;
-                                       else
-                                               Slot.Height = (int)Math.Round ((double)(Parent.ClientRectangle.Height * Height) / 100.0);
-
-                                       if (Slot.Height < 0)
-                                               return false;
-
-                                       //size constrain
-                                       if (Slot.Height < minimumSize.Height) {
-                                               Slot.Height = minimumSize.Height;
-                                               //NotifyValueChanged ("HeightPolicy", Measure.Stretched);
-                                       } else if (Slot.Height > maximumSize.Height && maximumSize.Height > 0) {
-                                               Slot.Height = maximumSize.Height;
-                                               //NotifyValueChanged ("HeightPolicy", Measure.Stretched);
-                                       }
-                               } else
-                                       Slot.Height = 0;
-
-                               if (LastSlots.Height == Slot.Height)
-                                       break;
-
-                               IsDirty = true;
-
-                               OnLayoutChanges (layoutType);
-
-                               LastSlots.Height = Slot.Height;
-                               break;
-                       }
-
-                       //if no layouting remains in queue for item, registre for redraw
-                       if (this.registeredLayoutings == LayoutingType.None && IsDirty)
-                               IFace.EnqueueForRepaint (this);
-
-                       return true;
-               }
-               #endregion
-
-               #region Rendering
-               /// <summary> This is the common overridable drawing routine to create new widget </summary>
-               protected virtual void onDraw(Context gr)
-               {
-                       #if DEBUG_LOG
-                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GODraw, this);
-                       #endif
-
-                       Rectangle rBack = new Rectangle (Slot.Size);
-
-                       background.SetAsSource (gr, rBack);
-                       CairoHelpers.CairoRectangle (gr, rBack, cornerRadius);
-                       gr.Fill ();
-
-                       #if DEBUG_LOG
-                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
-                       #endif
-               }
-
-               /// <summary>
-               /// Internal drawing context creation on a cached surface limited to slot size
-               /// this trigger the effective drawing routine </summary>
-               protected virtual void RecreateCache ()
-               {
-                       #if DEBUG_LOG
-                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GORecreateCache, this);
-                       #endif
-
-                       /*if (bmp == null)
-                               bmp = IFace.surf.CreateSimilar (Content.ColorAlpha, Slot.Width, Slot.Height);
-                       else if (LastPaintedSlot.Width != Slot.Width || LastPaintedSlot.Height != Slot.Height)
-                               bmp.SetSize (Slot.Width, Slot.Height);*/
-                       bmp?.Dispose ();
-                       //bmp = IFace.surf.CreateSimilar (Content.ColorAlpha, Slot.Width, Slot.Height);
-                       bmp = new ImageSurface(Format.Argb32, Slot.Width, Slot.Height);
-
-                       using (Context gr = new Context (bmp)) {
-                               gr.Antialias = Interface.Antialias;
-                               onDraw (gr);
-                       }
-
-                       IsDirty = false;
-
-                       #if DEBUG_LOG
-                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
-                       #endif
-               }
-               protected virtual void UpdateCache(Context ctx){
-                       #if DEBUG_LOG
-                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOUpdateCacheAndPaintOnCTX, this);
-                       #endif
-
-                       Rectangle rb = Slot + Parent.ClientRectangle.Position;
-                       if (clearBackground) {
-                                       ctx.Save ();
-                                       ctx.Operator = Operator.Clear;
-                                       ctx.Rectangle (rb);
-                                       ctx.Fill ();
-                                       ctx.Restore ();
-                       }
-
-                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
-                       ctx.Paint ();
-                       Clipping.Dispose ();
-                       Clipping = new Region ();
-                       #if DEBUG_LOG
-                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
-                       #endif
-               }
-               /// <summary> Chained painting routine on the parent context of the actual cached version
-               /// of the widget </summary>
-               public virtual void Paint (ref Context ctx)
-               {
-                       #if DEBUG_LOG
-                       DebugLog.AddEvent(DbgEvtType.GOPaint, this);
-                       #endif
-                       //TODO:this test should not be necessary
-                       if (Slot.Height < 0 || Slot.Width < 0 || parent == null)
-                               return;
-                       lock (this) {
-                               if (cacheEnabled) {
-                                       if (Slot.Width > Interface.MaxCacheSize || Slot.Height > Interface.MaxCacheSize)
-                                               cacheEnabled = false;
-                               }
-
-                               if (cacheEnabled) {
-                                       if (IsDirty)
-                                               RecreateCache ();
-
-                                       UpdateCache (ctx);
-                                       if (!isEnabled)                                         
-                                               paintDisabled (ctx, Slot + Parent.ClientRectangle.Position);                                    
-                               } else {
-                                       Rectangle rb = Slot + Parent.ClientRectangle.Position;
-                                       ctx.Save ();
-
-                                       ctx.Translate (rb.X, rb.Y);
-
-                                       onDraw (ctx);
-                                       if (!isEnabled)
-                                               paintDisabled (ctx, Slot);
-
-                                       ctx.Restore ();
-                               }
-                               LastPaintedSlot = Slot;
-                       }
-               }
-               void paintDisabled(Context gr, Rectangle rb){
-                       gr.Operator = Operator.Xor;
-                       gr.SetSourceRGBA (0.6, 0.6, 0.6, 0.3);
-                       gr.Rectangle (rb);
-                       gr.Fill ();
-                       gr.Operator = Operator.Over;
-               }
-               #endregion
-
-        #region Keyboard handling
-               public virtual void onKeyDown(object sender, KeyEventArgs e){
-                       if (KeyDown != null)
-                               KeyDown.Invoke (this, e);
-                       else if (!e.Handled)
-                               FocusParent?.onKeyDown (sender, e);
-               }
-               public virtual void onKeyUp(object sender, KeyEventArgs e){
-                       if (KeyUp != null)
-                               KeyUp.Invoke (this, e);
-                       else if (!e.Handled)
-                               FocusParent?.onKeyUp (sender, e);
-               }
-               public virtual void onKeyPress(object sender, KeyPressEventArgs e){
-                       if (KeyPress != null)
-                               KeyPress.Invoke (this, e);
-                       else if (!e.Handled)
-                               FocusParent?.onKeyPress (sender, e);
-               }
-        #endregion
-
-               #region Mouse handling
-               /// <summary>
-               /// Recursive local coordinate point test.
-               /// After test on parent, point m is in local coord system.
-               /// </summary>
-               /// <returns>return true, if point is in the bounds of this control</returns>
-               /// <param name="m">by ref point to test, init value is not kept</param>
-               public virtual bool PointIsIn(ref Point m)
-               {
-                       if (parent == null)
-                               return false;
-                       if (!(isVisible & isEnabled)||IsDragged)
-                               return false;
-                       if (!parent.PointIsIn(ref m))
-                               return false;
-                       m -= (parent.getSlot().Position + parent.ClientRectangle.Position) ;
-                       return Slot.ContainsOrIsEqual (m);                                      
-               }
-               public virtual bool MouseIsIn(Point m)
-               {                       
-                       return (!(isVisible & isEnabled)||IsDragged) ? false : PointIsIn (ref m);
-               }
-               public virtual void checkHoverWidget(MouseMoveEventArgs e)
-               {
-                       if (IFace.HoverWidget != this) {
-                               IFace.HoverWidget = this;
-                               onMouseEnter (this, e);
-                       }
-
-                       //this.onMouseMove (this, e);//without this, window border doesn't work, should be removed
-               }
-               public virtual void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       if (allowDrag & hasFocus & e.Mouse.LeftButton == ButtonState.Pressed) {
-                               if (IFace.DragAndDropOperation == null) {
-                                       IFace.DragAndDropOperation = new DragDropEventArgs (this);
-                                       onStartDrag (this, IFace.DragAndDropOperation);
-                               }
-                       }
-
-                       //dont bubble event if dragged, mouse move is routed directely from iface
-                       //to let other control behind have mouse entering
-                       if (isDragged)
-                               return;
-
-                       if (MouseMove != null)
-                               MouseMove.Invoke (this, e);                     
-                       else if (!e.Handled)
-                               FocusParent?.onMouseMove (sender, e);
-
-
-               }
-               public virtual void onMouseDown(object sender, MouseButtonEventArgs e){
-#if DEBUG_FOCUS
-                       Debug.WriteLine("MOUSE DOWN => " + this.ToString());
-#endif
-
-                       if (e.Button == MouseButton.Right && contextCommands != null) {
-                               IFace.ShowContextMenu (this);
-                               e.Handled = true;
-                       }
-
-                       if (MouseDown != null)
-                               MouseDown?.Invoke (this, e);
-                       else if (!e.Handled)
-                               FocusParent?.onMouseDown (sender, e);
-               }
-               public virtual void onMouseUp(object sender, MouseButtonEventArgs e){
-#if DEBUG_FOCUS
-                       Debug.WriteLine("MOUSE UP => " + this.ToString());
-#endif
-
-                       if (IFace.DragAndDropOperation != null){
-                               if (IFace.DragAndDropOperation.DragSource == this) {
-                                       if (IFace.DragAndDropOperation.DropTarget != null)
-                                               onDrop (this, IFace.DragAndDropOperation);
-                                       else
-                                               onEndDrag (this, IFace.DragAndDropOperation);
-                                       IFace.DragAndDropOperation = null;
-                               }
-                       }
-                       if (MouseUp != null)
-                               MouseUp.Invoke (this, e);
-                       else if (!e.Handled)
-                               FocusParent?.onMouseUp (sender, e);
-               }
-               public virtual void onMouseClick(object sender, MouseButtonEventArgs e){
-#if DEBUG_FOCUS
-                       Debug.WriteLine("CLICK => " + this.ToString());
-#endif
-                       if (MouseClick != null)
-                               MouseClick.Invoke (this, e);
-                       else if (!e.Handled)
-                               FocusParent?.onMouseClick (sender, e);
-               }
-               public virtual void onMouseDoubleClick(object sender, MouseButtonEventArgs e){
-#if DEBUG_FOCUS
-                       Debug.WriteLine("DOUBLE CLICK => " + this.ToString());
-#endif
-                       if (MouseDoubleClick != null)                   
-                               MouseDoubleClick.Invoke (this, e);
-                       else if (!e.Handled)
-                               FocusParent?.onMouseDoubleClick (sender, e);
-               }
-               public virtual void onMouseWheel(object sender, MouseWheelEventArgs e){
-                       if (MouseWheelChanged != null)
-                               MouseWheelChanged.Invoke (this, e);
-                       else if (!e.Handled)
-                               FocusParent?.onMouseWheel (sender, e);
-               }
-               public virtual void onMouseEnter(object sender, MouseMoveEventArgs e)
-               {
-                       #if DEBUG_FOCUS
-                       Debug.WriteLine("MouseEnter => " + this.ToString());
-#endif
-
-                       IFace.MouseCursor = mouseCursor;
-
-                       if (IFace.DragAndDropOperation != null) {
-                               Widget g = this;
-                               while (g != null) {
-                                       if (g.AllowDrop) {
-                                               if (IFace.DragAndDropOperation.DragSource != this && IFace.DragAndDropOperation.DropTarget != this) {
-                                                       if (IFace.DragAndDropOperation.DropTarget != null)
-                                                               IFace.DragAndDropOperation.DropTarget.onDragLeave (this, IFace.DragAndDropOperation);
-                                                       g.onDragEnter (this, IFace.DragAndDropOperation);
-                                               }
-                                               break;
-                                       }
-                                       g = g.FocusParent;
-                               }
-                       }
-
-                       MouseEnter.Raise (this, e);
-               }
-               public virtual void onMouseLeave(object sender, MouseMoveEventArgs e)
-               {
-                       #if DEBUG_FOCUS
-                       Debug.WriteLine("MouseLeave => " + this.ToString());
-                       #endif
-
-                       MouseLeave.Raise (this, e);
-               }
-
-               #endregion
-
-               protected virtual void onFocused(object sender, EventArgs e){
-                       #if DEBUG_FOCUS
-                       Debug.WriteLine("Focused => " + this.ToString());
-                       #endif
-                       Focused.Raise (this, e);
-               }
-               protected virtual void onUnfocused(object sender, EventArgs e){
-                       #if DEBUG_FOCUS
-                       Debug.WriteLine("UnFocused => " + this.ToString());
-                       #endif
-                       Unfocused.Raise (this, e);
-               }
-
-               public virtual void onEnable(object sender, EventArgs e){
-                       Enabled.Raise (this, e);
-               }
-               public virtual void onDisable(object sender, EventArgs e){
-                       Disabled.Raise (this, e);
-               }
-               protected virtual void onParentChanged(object sender, DataSourceChangeEventArgs e) {
-                       ParentChanged.Raise (this, e);
-                       if (logicalParent == null)
-                               LogicalParentChanged.Raise (this, e);
-               }
-               protected virtual void onLogicalParentChanged(object sender, DataSourceChangeEventArgs e) {
-                       LogicalParentChanged.Raise (this, e);
-               }
-               internal void ClearTemplateBinding(){
-                       #if DEBUG_UPDATE
-                       Debug.WriteLine (string.Format("ClearTemplateBinding: {0}", this.ToString()));
-                       #endif
-                       if (ValueChanged == null)
-                               return;
-                       EventInfo eiEvt = this.GetType().GetEvent ("ValueChanged");
-                       foreach (Delegate d in ValueChanged.GetInvocationList()) {
-                               if (d.Method.Name == "dyn_tmpValueChanged") {
-                                       eiEvt.RemoveEventHandler (this, d);
-                                       #if DEBUG_BINDING
-                                       Debug.WriteLine ("\t{0} template binding handler removed in {1} for: {2}", d.Method.Name, this, "ValueChanged");
-                                       #endif
-                               }
-                       }
-               }
-               public override string ToString ()
-               {
-                       string tmp ="";
-
-                       if (Parent != null)
-                               tmp = Parent.ToString () + tmp;
-                       #if DEBUG_LAYOUTING
-                       return Name == "unamed" ? tmp + "." + this.GetType ().Name + GraphicObjects.IndexOf(this).ToString(): tmp + "." + Name;
-                       #else
-                       return string.IsNullOrEmpty(Name) ? tmp + "." + this.GetType ().Name : tmp + "." + Name;
-                       #endif
-               }
-               /// <summary>
-               /// Checks to handle when widget is removed from the visible graphic tree
-               /// </summary>
-               void unshownPostActions () {
-                       if (IFace.HoverWidget != null) {
-                               if (IFace.HoverWidget.IsOrIsInside (this)) {
-                                       IFace.HoverWidget = null;
-                                       IFace.OnMouseMove (IFace.Mouse.X, IFace.Mouse.Y);
-                               }
-                       }
-                       if (IFace.ActiveWidget != null) {
-                               if (IFace.ActiveWidget.IsOrIsInside (this))
-                                       IFace.ActiveWidget = null;
-                       }
-                       if (IFace.FocusedWidget != null) {
-                               if (IFace.FocusedWidget.IsOrIsInside (this))
-                                       IFace.FocusedWidget = null;
-                       }                                       
-               }
-       }
-}
diff --git a/Crow/src/GraphicObjects/Window.cs b/Crow/src/GraphicObjects/Window.cs
deleted file mode 100644 (file)
index 22ad640..0000000
+++ /dev/null
@@ -1,466 +0,0 @@
-//
-// Window.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.Xml.Serialization;
-using System.ComponentModel;
-using System.Diagnostics;
-
-namespace Crow
-{
-       public class Window : TemplatedContainer
-       {
-               public enum Direction
-               {
-                       None,
-                       N,
-                       S,
-                       E,
-                       W,
-                       NW,
-                       NE,
-                       SW,
-                       SE,
-               }
-
-               string _icon;
-               bool resizable;
-               bool movable;
-               bool modal;
-               protected bool hoverBorder = false;
-               bool alwaysOnTop = false;
-               Fill titleBarBackground = Color.SteelBlue;
-               Fill titleBarForeground = Color.White;
-
-               Rectangle savedBounds;
-               bool _minimized = false;
-
-               Direction currentDirection = Direction.None;
-
-               #region Events
-               public event EventHandler Closing;
-               public event EventHandler Maximized;
-               public event EventHandler Unmaximized;
-               public event EventHandler Minimize;
-               #endregion
-
-               #region CTOR
-               protected Window() : base(){}
-               public Window (Interface iface) : base(iface){}
-               #endregion
-
-               #region TemplatedContainer overrides
-               protected override void loadTemplate(Widget template = null)
-               {
-                       base.loadTemplate (template);
-
-                       NotifyValueChanged ("ShowNormal", false);
-                       NotifyValueChanged ("ShowMinimize", true);
-                       NotifyValueChanged ("ShowMaximize", true);
-               }
-               #endregion
-
-               #region public properties
-               [DefaultValue("#Crow.Icons.crow.svg")]
-               public string Icon {
-                       get { return _icon; } 
-                       set {
-                               if (_icon == value)
-                                       return;
-                               _icon = value;
-                               NotifyValueChanged ("Icon", _icon);
-                       }
-               } 
-               /// <summary>
-               /// Background of the title bar if any.
-               /// </summary>
-               [DefaultValue("vgradient|0:Onyx|1:SteelBlue")]
-               public virtual Fill TitleBarBackground {
-                       get { return titleBarBackground; }
-                       set {
-                               if (titleBarBackground == value)
-                                       return;
-                               titleBarBackground = value;
-                               NotifyValueChanged ("TitleBarBackground", titleBarBackground);
-                               RegisterForRedraw ();
-                       }
-               }
-               /// <summary>
-               /// Foreground of the title bar, usualy used for the window caption color.
-               /// </summary>
-               [DefaultValue("White")]
-               public virtual Fill TitleBarForeground {
-                       get { return titleBarForeground; }
-                       set {
-                               if (titleBarForeground == value)
-                                       return;
-                               titleBarForeground = value;
-                               NotifyValueChanged ("TitleBarForeground", titleBarForeground);
-                               RegisterForRedraw ();
-                       }
-               }
-               [DefaultValue(true)]
-               public bool Resizable {
-                       get {
-                               return resizable;
-                       }
-                       set {
-                               if (resizable == value)
-                                       return;
-                               resizable = value;
-                               NotifyValueChanged ("Resizable", resizable);
-                       }
-               }
-               [DefaultValue(true)]
-               public bool Movable {
-                       get {
-                               return movable;
-                       }
-                       set {
-                               if (movable == value)
-                                       return;
-                               movable = value;
-                               NotifyValueChanged ("Movable", movable);
-                       }
-               }
-               [DefaultValue(false)]
-               public bool Modal {
-                       get {
-                               return modal;
-                       }
-                       set {
-                               if (modal == value)
-                                       return;
-                               modal = value;
-                               NotifyValueChanged ("Modal", modal);
-                       }
-               }
-               [DefaultValue(false)]
-               public bool IsMinimized {
-                       get { return _minimized; }
-                       set{
-                               if (value == IsMinimized)
-                                       return;
-
-                               _minimized = value;
-                               _contentContainer.Visible = !_minimized;
-
-                               NotifyValueChanged ("IsMinimized", _minimized);
-                       }
-               }
-               [XmlIgnore]public bool IsMaximized {
-                       get { return Width == Measure.Stretched & Height == Measure.Stretched & !_minimized; }
-               }
-               [XmlIgnore]public bool IsNormal {
-                       get { return !(IsMaximized|_minimized); }
-               }
-               [DefaultValue(false)]
-               public bool AlwaysOnTop {
-                       get {
-                               return modal ? true : alwaysOnTop;
-                       }
-                       set {
-                               if (alwaysOnTop == value)
-                                       return;
-                               
-                               alwaysOnTop = value;
-
-                               if (AlwaysOnTop && Parent != null)
-                                       IFace.PutOnTop (this);
-
-                               NotifyValueChanged ("AlwaysOnTop", AlwaysOnTop);
-                       }
-               }
-//             [DefaultValue(WindowState.Normal)]
-//             public virtual WindowState State {
-//                     get { return _state; }
-//                     set {
-//                             if (_state == value)
-//                                     return;
-//                             _state = value;
-//                             NotifyValueChanged ("State", _state);
-//                             NotifyValueChanged ("IsNormal", IsNormal);
-//                             NotifyValueChanged ("IsMaximized", IsMaximized);
-//                             NotifyValueChanged ("IsMinimized", IsMinimized);
-//                             NotifyValueChanged ("IsNotMinimized", IsNotMinimized);
-//                     }
-//             } 
-               #endregion
-
-               /// <summary>
-               /// Moves the and resize with the same function entry point, the direction give the kind of move or resize
-               /// </summary>
-               /// <param name="XDelta">mouse delta on the X axis</param>
-               /// <param name="YDelta">mouse delta on the Y axis</param>
-               /// <param name="currentDirection">Current Direction of the operation, none for moving, other value for resizing in the given direction</param>
-               public void MoveAndResize (int XDelta, int YDelta, Direction currentDirection = (Direction)0) {
-                       int currentLeft = this.Left;
-                       int currentTop = this.Top;
-                       int currentWidth, currentHeight;
-
-                       if (currentLeft == 0) {
-                               currentLeft = this.Slot.Left;
-                               this.Left = currentLeft;
-                       }
-                       if (currentTop == 0) {
-                               currentTop = this.Slot.Top;
-                               this.Top = currentTop;
-                       }
-                       if (this.Width.IsFixed)
-                               currentWidth = this.Width;
-                       else
-                               currentWidth = this.Slot.Width;
-
-                       if (this.Height.IsFixed)
-                               currentHeight = this.Height;
-                       else
-                               currentHeight = this.Slot.Height;
-
-                       switch (currentDirection) {
-                       case Direction.None:
-                               this.Left = currentLeft + XDelta;                               
-                               this.Top = currentTop + YDelta;
-                               break;
-                       case Direction.N:
-                               this.Height = currentHeight - YDelta;
-                               if (this.Height == currentHeight - YDelta)
-                                       this.Top = currentTop + YDelta;
-                               break;
-                       case Direction.S:
-                               this.Height = currentHeight + YDelta;
-                               break;
-                       case Direction.W:
-                               this.Width = currentWidth - XDelta;
-                               if (this.Width == currentWidth - XDelta)
-                                       this.Left = currentLeft + XDelta;
-                               break;
-                       case Direction.E:
-                               this.Width = currentWidth + XDelta;
-                               break;
-                       case Direction.NW:
-                               this.Height = currentHeight - YDelta;
-                               if (this.Height == currentHeight - YDelta)
-                                       this.Top = currentTop + YDelta;
-                               this.Width = currentWidth - XDelta;
-                               if (this.Width == currentWidth - XDelta)
-                                       this.Left = currentLeft + XDelta;
-                               break;
-                       case Direction.NE:
-                               this.Height = currentHeight - YDelta;
-                               if (this.Height == currentHeight - YDelta)
-                                       this.Top = currentTop + YDelta;
-                               this.Width = currentWidth + XDelta;
-                               break;
-                       case Direction.SW:
-                               this.Width = currentWidth - XDelta;
-                               if (this.Width == currentWidth - XDelta)
-                                       this.Left = currentLeft + XDelta;
-                               this.Height = currentHeight + YDelta;
-                               break;
-                       case Direction.SE:
-                               this.Height = currentHeight + YDelta;
-                               this.Width = currentWidth + XDelta;
-                               break;
-                       }                       
-               }
-
-               #region GraphicObject Overrides
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       base.onMouseMove (sender, e);
-
-                       Interface otkgw = IFace;
-
-                       /*if (!hoverBorder) {
-                               currentDirection = Direction.None;
-                               IFace.MouseCursor = MouseCursor.Arrow;
-                               return;
-                       }*/
-
-                       if (this.HasFocus && movable) {
-                               if (e.Mouse.IsButtonDown (MouseButton.Left)) {
-                                       MoveAndResize (e.XDelta, e.YDelta, currentDirection);
-                                       return;
-                               }
-                       }
-                       if (Resizable) {
-                               Direction lastDir = currentDirection;
-
-                               if (Math.Abs (e.Position.Y - this.Slot.Y) < Interface.BorderThreshold) {
-                                       if (Math.Abs (e.Position.X - this.Slot.X) < Interface.BorderThreshold)
-                                               currentDirection = Direction.NW;
-                                       else if (Math.Abs (e.Position.X - this.Slot.Right) < Interface.BorderThreshold)
-                                               currentDirection = Direction.NE;
-                                       else
-                                               currentDirection = Direction.N;
-                               } else if (Math.Abs (e.Position.Y - this.Slot.Bottom) < Interface.BorderThreshold) {
-                                       if (Math.Abs (e.Position.X - this.Slot.X) < Interface.BorderThreshold)
-                                               currentDirection = Direction.SW;
-                                       else if (Math.Abs (e.Position.X - this.Slot.Right) < Interface.BorderThreshold)
-                                               currentDirection = Direction.SE;
-                                       else
-                                               currentDirection = Direction.S;
-                               } else if (Math.Abs (e.Position.X - this.Slot.X) < Interface.BorderThreshold)
-                                       currentDirection = Direction.W;
-                               else if (Math.Abs (e.Position.X - this.Slot.Right) < Interface.BorderThreshold)
-                                       currentDirection = Direction.E;
-                               else
-                                       currentDirection = Direction.None;
-
-                               if (currentDirection != lastDir) {
-                                       switch (currentDirection) {
-                                       case Direction.None:
-                                               otkgw.MouseCursor = MouseCursor.Move;
-                                               break;
-                                       case Direction.N:
-                                               otkgw.MouseCursor = MouseCursor.Top;
-                                               break;
-                                       case Direction.S:
-                                               otkgw.MouseCursor = MouseCursor.Bottom;
-                                               break;
-                                       case Direction.E:
-                                               otkgw.MouseCursor = MouseCursor.Right;
-                                               break;
-                                       case Direction.W:
-                                               otkgw.MouseCursor = MouseCursor.Left;
-                                               break;
-                                       case Direction.NW:
-                                               otkgw.MouseCursor = MouseCursor.TopLeft;
-                                               break;
-                                       case Direction.NE:
-                                               otkgw.MouseCursor = MouseCursor.TopRight;
-                                               break;
-                                       case Direction.SW:
-                                               otkgw.MouseCursor = MouseCursor.BottomLeft;
-                                               break;
-                                       case Direction.SE:
-                                               otkgw.MouseCursor = MouseCursor.BottomRight;
-                                               break;
-                                       }
-                               }                               
-                       }                               
-               }
-               public override void onMouseDown (object sender, MouseButtonEventArgs e)
-               {
-                       base.onMouseDown (sender, e);
-               }
-               public override bool MouseIsIn (Point m)
-               {
-                       return modal ? true : base.MouseIsIn (m);
-               }
-               #endregion
-
-               protected void onMaximized (object sender, EventArgs e){
-                       lock (IFace.LayoutMutex) {
-                               if (!IsMinimized)
-                                       savedBounds = this.LastPaintedSlot;
-                               this.Left = this.Top = 0;
-                               this.RegisterForLayouting (LayoutingType.Positioning);
-                               this.Width = this.Height = Measure.Stretched;
-                               IsMinimized = false;
-                               Resizable = false;
-                               NotifyValueChanged ("ShowNormal", true);
-                               NotifyValueChanged ("ShowMinimize", true);
-                               NotifyValueChanged ("ShowMaximize", false);
-                       }
-
-                       Maximized.Raise (sender, e);
-               }
-               protected void onUnmaximized (object sender, EventArgs e){
-                       lock (IFace.LayoutMutex) {
-                               this.Left = savedBounds.Left;
-                               this.Top = savedBounds.Top;
-                               this.Width = savedBounds.Width;
-                               this.Height = savedBounds.Height;
-                               IsMinimized = false;
-                               Resizable = true;
-                               NotifyValueChanged ("ShowNormal", false);
-                               NotifyValueChanged ("ShowMinimize", true);
-                               NotifyValueChanged ("ShowMaximize", true);
-                       }
-
-                       Unmaximized.Raise (sender, e);
-               }
-               protected void onMinimized (object sender, EventArgs e){
-                       lock (IFace.LayoutMutex) {
-                               if (IsNormal)
-                                       savedBounds = this.LastPaintedSlot;
-                               Width = 200;
-                               Height = 20;
-                               Resizable = false;
-                               IsMinimized = true;
-                               NotifyValueChanged ("ShowNormal", true);
-                               NotifyValueChanged ("ShowMinimize", false);
-                               NotifyValueChanged ("ShowMaximize", true);
-                       }
-
-                       Minimize.Raise (sender, e);
-               }
-               protected virtual void onBorderMouseLeave (object sender, MouseMoveEventArgs e)
-               {
-                       hoverBorder = false;
-                       currentDirection = Direction.None;
-                       IFace.MouseCursor = MouseCursor.Arrow;
-               }
-               protected virtual void onBorderMouseEnter (object sender, MouseMoveEventArgs e)
-               {
-                       hoverBorder = true;
-               }
-
-
-               protected void butQuitPress (object sender, MouseButtonEventArgs e)
-               {
-                       IFace.MouseCursor = MouseCursor.Arrow;
-                       close ();
-               }
-
-               protected virtual void close(){
-                       Closing.Raise (this, null);
-                       if (Parent is Interface)
-                               (Parent as Interface).DeleteWidget (this);
-                       else {
-                               Widget p = Parent as Widget;
-                               if (p is Group) {
-                                       lock (IFace.UpdateMutex) {
-                                               RegisterClip (p.ScreenCoordinates (p.LastPaintedSlot));
-                                               (p as Group).DeleteChild (this);
-                                       }
-                                       //(Parent as Group).RegisterForRedraw ();
-                               } else if (Parent is PrivateContainer)
-                                       (Parent as Container).Child = null;
-                       }
-               }
-
-               public static Window Show (Interface iface, string imlPath, bool modal = false){
-                       lock (iface.UpdateMutex) {
-                               Window w = iface.Load (imlPath) as Window;
-                               w.Modal = modal;
-                               return w;
-                       }
-               }
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/Wrapper.cs b/Crow/src/GraphicObjects/Wrapper.cs
deleted file mode 100644 (file)
index cc31985..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-//
-// Wrapper.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;
-
-namespace Crow
-{
-       /// <summary>
-       /// group control that arrange its children in a direction and jump to
-       /// the next line or row when no room is left
-       /// </summary>
-       public class Wrapper : GenericStack
-       {
-               #region CTOR
-               protected Wrapper() : base(){}
-               public Wrapper (Interface iface) : base(iface){}
-               #endregion
-
-               #region Group Overrides
-               public override void ChildrenLayoutingConstraints (ref LayoutingType layoutType)
-               {
-                       layoutType &= (~LayoutingType.Positioning);
-               }
-               public override void ComputeChildrenPositions()
-               {
-                       int dx = 0;
-                       int dy = 0;
-
-                       if (Orientation == Orientation.Vertical) {
-                               int tallestChild = 0;
-                               foreach (Widget c in Children) {
-                                       if (!c.Visible)
-                                               continue;
-                                       if (dx + c.Slot.Width > ClientRectangle.Width) {
-                                               dx = 0;
-                                               dy += tallestChild + Spacing;
-                                               c.Slot.X = dx;
-                                               c.Slot.Y = dy;
-                                               tallestChild = c.Slot.Height;
-                                       } else {
-                                               if (tallestChild < c.Slot.Height)
-                                                       tallestChild = c.Slot.Height;
-                                               c.Slot.X = dx;
-                                               c.Slot.Y = dy;
-                                       }
-                                       dx += c.Slot.Width + Spacing;
-                               }
-                       } else {
-                               int largestChild = 0;
-                               foreach (Widget c in Children) {
-                                       if (!c.Visible)
-                                               continue;
-                                       if (dy + c.Slot.Height > ClientRectangle.Height) {
-                                               dy = 0;
-                                               dx += largestChild + Spacing;
-                                               c.Slot.X = dx;
-                                               c.Slot.Y = dy;
-                                               largestChild = c.Slot.Width;
-                                       } else {
-                                               if (largestChild < c.Slot.Width)
-                                                       largestChild = c.Slot.Width;
-                                               c.Slot.X = dx;
-                                               c.Slot.Y = dy;
-                                       }
-                                       dy += c.Slot.Height + Spacing;
-                               }
-                       }
-                       IsDirty = true;
-               }
-               public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
-               {
-                       //children can't stretch in a wrapper
-                       Widget go = sender as Widget;
-                       //System.Diagnostics.Debug.WriteLine ("wrapper child layout change: " + go.LastSlots.ToString() + " => " + go.Slot.ToString());
-                       switch (arg.LayoutType) {
-                       case LayoutingType.Width:
-                               if (Orientation == Orientation.Horizontal && go.Width.Units == Unit.Percent){
-                                       go.Width = Measure.Fit;
-                                       return;
-                               }
-                               this.RegisterForLayouting (LayoutingType.Width);
-                               break;
-                       case LayoutingType.Height:
-                               if (Orientation == Orientation.Vertical && go.Height.IsRelativeToParent) {
-                                       go.Height = Measure.Fit;
-                                       return;
-                               }
-                               this.RegisterForLayouting (LayoutingType.Height);
-                               break;
-                       default:
-                               return;
-                       }
-                       this.RegisterForLayouting (LayoutingType.ArrangeChildren);
-               }
-               #endregion
-
-               #region GraphicObject Overrides
-               protected override int measureRawSize (LayoutingType lt)
-               {
-                       int tmp = 0;
-                       //Wrapper can't fit in the opposite direction of the wrapper, this func is called only if Fit
-                       if (lt == LayoutingType.Width) {
-                               if (Orientation == Orientation.Vertical) {
-                                       Width = Measure.Stretched;
-                                       return -1;
-                               } else if (RegisteredLayoutings.HasFlag (LayoutingType.Height))
-                                       return -1;
-                               else {
-                                       int dy = 0;
-                                       int largestChild = 0;
-
-                                       childrenRWLock.EnterReadLock();
-
-                                       foreach (Widget c in Children) {
-                                               if (!c.Visible)
-                                                       continue;
-                                               if (c.Height.IsRelativeToParent &&
-                                                   c.RegisteredLayoutings.HasFlag (LayoutingType.Height)) {
-                                                       childrenRWLock.ExitReadLock();
-                                                       return -1;
-                                               }
-                                               if (dy + c.Slot.Height > ClientRectangle.Height) {
-                                                       dy = 0;
-                                                       tmp += largestChild + Spacing;
-                                                       largestChild = c.Slot.Width;
-                                               } else if (largestChild < c.Slot.Width)
-                                                       largestChild = c.Slot.Width;
-
-                                               dy += c.Slot.Height + Spacing;
-                                       }
-
-                                       childrenRWLock.ExitReadLock ();
-
-                                       if (dy == 0)
-                                               tmp -= Spacing;
-                                       return tmp + largestChild + 2 * Margin;
-                               }
-                       } else if (Orientation == Orientation.Horizontal) {
-                               Height = Measure.Stretched;
-                               return -1;
-                       } else if (RegisteredLayoutings.HasFlag (LayoutingType.Width))
-                               return -1;
-                       else {
-                               int dx = 0;
-                               int tallestChild = 0;
-
-                               childrenRWLock.EnterReadLock();
-
-                               foreach (Widget c in Children) {
-                                       if (!c.Visible)
-                                               continue;
-                                       if (c.Width.IsRelativeToParent &&
-                                           c.RegisteredLayoutings.HasFlag (LayoutingType.Width)) {
-                                               childrenRWLock.ExitReadLock();
-                                               return -1;
-                                       }
-                                       if (dx + c.Slot.Width > ClientRectangle.Width) {
-                                               dx = 0;
-                                               tmp += tallestChild + Spacing;
-                                               tallestChild = c.Slot.Height;
-                                       } else if (tallestChild < c.Slot.Height)
-                                               tallestChild = c.Slot.Height;
-
-                                       dx += c.Slot.Width + Spacing;
-                               }
-
-                               childrenRWLock.ExitReadLock();
-
-                               if (dx == 0)
-                                       tmp -= Spacing;
-                               return tmp + tallestChild + 2 * Margin;
-                       }
-               }
-
-               public override bool UpdateLayout (LayoutingType layoutType)
-               {
-                       RegisteredLayoutings &= (~layoutType);
-
-                       if (layoutType == LayoutingType.ArrangeChildren) {
-                               if ((RegisteredLayoutings & LayoutingType.Sizing) != 0)
-                                       return false;
-
-                               ComputeChildrenPositions ();
-
-                               //if no layouting remains in queue for item, registre for redraw
-                               if (RegisteredLayoutings == LayoutingType.None && IsDirty)
-                                       IFace.EnqueueForRepaint (this);
-
-                               return true;
-                       }
-
-                       return base.UpdateLayout(layoutType);
-               }
-               public override void OnLayoutChanges (LayoutingType layoutType)
-               {
-                       #if DEBUG_LAYOUTING
-                       IFace.currentLQI.Slot = LastSlots;
-                       IFace.currentLQI.Slot = Slot;
-                       #endif
-                       switch (layoutType) {
-                       case LayoutingType.Width:
-                               foreach (Widget c in Children) {
-                                       if (c.Width.IsRelativeToParent)
-                                               c.RegisterForLayouting (LayoutingType.Width);
-                               }
-                               if (Height == Measure.Fit)
-                                       RegisterForLayouting (LayoutingType.Height);
-                               RegisterForLayouting (LayoutingType.X);
-                               break;
-                       case LayoutingType.Height:
-                               foreach (Widget c in Children) {
-                                       if (c.Height.IsRelativeToParent)
-                                               c.RegisterForLayouting (LayoutingType.Height);
-                               }
-                               if (Width == Measure.Fit)
-                                       RegisterForLayouting (LayoutingType.Width);
-                               RegisterForLayouting (LayoutingType.Y);
-                               break;
-                       default:
-                               return;
-                       }
-                       RegisterForLayouting (LayoutingType.ArrangeChildren);
-                       raiseLayoutChanged (new LayoutingEventArgs (layoutType));
-               }
-               #endregion
-       }
-}
-
diff --git a/Crow/src/GraphicObjects/XmlIgnoreAttribute.cs b/Crow/src/GraphicObjects/XmlIgnoreAttribute.cs
deleted file mode 100644 (file)
index 29e5bf6..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Expandable.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;
-
-namespace Crow
-{
-    public class XmlIgnoreAttribute : Attribute
-    {
-    }
-}
\ No newline at end of file
diff --git a/Crow/src/Widgets/Border.cs b/Crow/src/Widgets/Border.cs
new file mode 100644 (file)
index 0000000..e5a16ec
--- /dev/null
@@ -0,0 +1,273 @@
+//
+// Border.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.Xml.Serialization;
+using System.ComponentModel;
+using System.Diagnostics;
+using Crow.Cairo;
+
+namespace Crow
+{
+       /// <summary>
+       /// provide an easy way to get 3d border for buttons
+       /// </summary>
+       public enum BorderStyle {
+               Normal,
+               Raised,
+               Sunken
+       };
+
+       /// <summary>
+       /// simple container with border
+       /// </summary>
+       public class Border : Container
+       {
+               #region CTOR
+               protected Border () : base(){}
+               public Border (Interface iface) : base(iface){}
+               #endregion
+
+               #region private fields
+               int _borderWidth;
+               BorderStyle _borderStyle;
+               Fill raisedColor = Color.Grey;
+               Fill sunkenColor = Color.DimGrey;
+               #endregion
+
+               #region public properties
+               /// <summary>
+               /// use to define the colors of the 3d border
+               /// </summary>
+               
+               public virtual Fill RaisedColor {
+                       get { return raisedColor; }
+                       set {
+                               if (raisedColor == value)
+                                       return;
+                               raisedColor = value;
+                               NotifyValueChanged ("RaisedColor", raisedColor);
+                               RegisterForRedraw ();
+                       }
+               }
+               /// <summary>
+               /// use to define the colors of the 3d border
+               /// </summary>
+               
+               public virtual Fill SunkenColor {
+                       get { return sunkenColor; }
+                       set {
+                               if (sunkenColor == value)
+                                       return;
+                               sunkenColor = value;
+                               NotifyValueChanged ("SunkenColor", sunkenColor);
+                               RegisterForRedraw ();
+                       }
+               }
+               /// <summary>
+               /// border width in pixels
+               /// </summary>
+               [DefaultValue(1)]
+               public virtual int BorderWidth {
+                       get { return _borderWidth; }
+                       set {
+                               _borderWidth = value;
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary>
+               /// allow 3d border effects
+               /// </summary>
+               [DefaultValue(BorderStyle.Normal)]
+               public virtual BorderStyle BorderStyle {
+                       get { return _borderStyle; }
+                       set {
+                               if (_borderStyle == value)
+                                       return;
+                               _borderStyle = value;
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               #endregion
+
+               #region GraphicObject override
+               [XmlIgnore]public override Rectangle ClientRectangle {
+                       get {
+                               Rectangle cb = base.ClientRectangle;
+                               cb.Inflate (- BorderWidth);
+                               return cb;
+                       }
+               }
+
+               protected override int measureRawSize (LayoutingType lt)
+               {
+                       int tmp = base.measureRawSize (lt);
+                       return tmp < 0 ? tmp : tmp + 2 * BorderWidth;
+               }
+               protected override void onDraw (Context gr)
+               {
+                       drawborder2 (gr);
+
+                       gr.Save ();
+                       if (ClipToClientRect) {
+                               //clip to client zone
+                               CairoHelpers.CairoRectangle (gr, ClientRectangle,Math.Max(0.0, CornerRadius-Margin));
+                               gr.Clip ();
+                       }
+
+                       if (child != null)
+                               child.Paint (ref gr);
+                       gr.Restore ();
+               }
+               void drawborder2(Context gr){
+                       Rectangle rBack = new Rectangle (Slot.Size);
+
+                       //rBack.Inflate (-Margin);
+                       //                      if (BorderWidth > 0)
+                       //                              rBack.Inflate (-BorderWidth / 2);
+
+                       Background.SetAsSource (gr, rBack);
+                       CairoHelpers.CairoRectangle(gr, rBack, CornerRadius);
+                       gr.Fill ();
+
+
+                       if (BorderStyle == BorderStyle.Normal) {
+                               if (BorderWidth > 0) {
+                                       Foreground.SetAsSource (gr, rBack);
+                                       CairoHelpers.CairoRectangle (gr, rBack, CornerRadius, BorderWidth);
+                               }
+                       } else {
+                               gr.LineWidth = 1.0;
+                               if (CornerRadius > 0.0) {
+                                       double radius = CornerRadius;
+                                       if ((radius > rBack.Height / 2.0) || (radius > rBack.Width / 2.0))
+                                               radius = Math.Min (rBack.Height / 2.0, rBack.Width / 2.0);
+                                       gr.SetSourceColor (sunkenColor);
+                                       gr.MoveTo (0.5 + rBack.Left, -0.5 + rBack.Bottom - radius);
+                                       gr.ArcNegative (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom - radius, radius, Math.PI, Math.PI * 0.75);
+                                       gr.MoveTo (0.5 + rBack.Left, -0.5 + rBack.Bottom - radius);
+                                       gr.LineTo (0.5 + rBack.Left, 0.5 + rBack.Top + radius);
+                                       gr.Arc (0.5 + rBack.Left + radius, 0.5 + rBack.Top + radius, radius, Math.PI, Math.PI * 1.5);
+                                       gr.LineTo (-0.5 + rBack.Right - radius, 0.5 + rBack.Top);
+                                       gr.Arc (-0.5 + rBack.Right - radius, 0.5 + rBack.Top + radius, radius, Math.PI * 1.5, Math.PI * 1.75);
+                                       gr.Stroke ();
+                                       if (BorderStyle == BorderStyle.Raised) {
+                                               gr.MoveTo (-1.5 + rBack.Right, 1.5 + rBack.Top + radius);
+                                               gr.ArcNegative (-0.5 + rBack.Right - radius, 0.5 + rBack.Top + radius, radius - 1.0, 0, -Math.PI * 0.25);
+                                               gr.MoveTo (-1.5 + rBack.Right, 1.5 + rBack.Top + radius);
+                                               gr.LineTo (-1.5 + rBack.Right, -1.5 + rBack.Bottom - radius);
+                                               gr.Arc (-0.5 + rBack.Right - radius, -0.5 + rBack.Bottom - radius, radius - 1.0, 0, Math.PI / 2.0);
+                                               gr.LineTo (1.5 + rBack.Left + radius, -1.5 + rBack.Bottom);
+                                               gr.Arc (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom - radius, radius - 1.0, Math.PI / 2.0, Math.PI * 0.75);
+                                               gr.Stroke ();
+
+                                               gr.SetSourceColor (raisedColor);
+                                               gr.MoveTo (1.5 + rBack.Left, -1.5 + rBack.Bottom - radius);
+                                               gr.ArcNegative (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom - radius, radius - 1.0, Math.PI, Math.PI * 0.75);
+                                               gr.MoveTo (1.5 + rBack.Left, -1.5 + rBack.Bottom - radius);
+                                               gr.LineTo (1.5 + rBack.Left, 1.5 + rBack.Top + radius);
+                                               gr.Arc (0.5 + rBack.Left + radius, 0.5 + rBack.Top + radius, radius - 1.0, Math.PI, Math.PI * 1.5);
+                                               gr.LineTo (-1.5 + rBack.Right - radius, 1.5 + rBack.Top);
+                                               gr.Arc (-0.5 + rBack.Right - radius, 0.5 + rBack.Top + radius, radius - 1.0, Math.PI * 1.5, Math.PI * 1.75);
+                                       } else {
+                                               gr.Stroke ();
+                                               gr.SetSourceColor (raisedColor);
+                                       }
+                                       gr.MoveTo (-0.5 + rBack.Right, 0.5 + rBack.Top + radius);
+                                       gr.ArcNegative (-0.5 + rBack.Right - radius, 0.5 + rBack.Top + radius, radius, 0, -Math.PI * 0.25);
+                                       gr.MoveTo (-0.5 + rBack.Right, 0.5 + rBack.Top + radius);
+                                       gr.LineTo (-0.5 + rBack.Right, -0.5 + rBack.Bottom - radius);
+                                       gr.Arc (-0.5 + rBack.Right - radius, -0.5 + rBack.Bottom - radius, radius, 0, Math.PI / 2.0);
+                                       gr.LineTo (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom);
+                                       gr.Arc (0.5 + rBack.Left + radius, -0.5 + rBack.Bottom - radius, radius, Math.PI / 2.0, Math.PI * 0.75);
+                                       gr.Stroke ();
+                               } else {
+                                       gr.SetSourceColor (sunkenColor);
+                                       gr.MoveTo (0.5 + rBack.Left, rBack.Bottom);
+                                       gr.LineTo (0.5 + rBack.Left, 0.5 + rBack.Y);
+                                       gr.LineTo (rBack.Right, 0.5 + rBack.Y);
+                                       if (BorderStyle == BorderStyle.Raised) {
+                                               gr.MoveTo (-1.5 + rBack.Right, 2.0 + rBack.Y);
+                                               gr.LineTo (-1.5 + rBack.Right, -1.5 + rBack.Bottom);
+                                               gr.LineTo (2.0 + rBack.Left, -1.5 + rBack.Bottom);
+                                               gr.Stroke ();
+                                               gr.SetSourceColor (raisedColor);
+                                               gr.MoveTo (1.5 + rBack.Left, -1.0 + rBack.Bottom);
+                                               gr.LineTo (1.5 + rBack.Left, 1.5 + rBack.Y);
+                                               gr.LineTo (rBack.Right, 1.5 + rBack.Y);
+                                       } else {
+                                               gr.Stroke ();
+                                               gr.SetSourceColor (raisedColor);
+                                       }
+                                       gr.MoveTo (-0.5 + rBack.Right, 1.5 + rBack.Y);
+                                       gr.LineTo (-0.5 + rBack.Right, -0.5 + rBack.Bottom);
+                                       gr.LineTo (1.0 + rBack.Left, -0.5 + rBack.Bottom);
+                                       gr.Stroke ();
+                               }
+                       }
+               }
+               void drawborder1(Context gr){
+                       Rectangle rBack = new Rectangle (Slot.Size);
+
+                       //rBack.Inflate (-Margin);
+                       //                      if (BorderWidth > 0)
+                       //                              rBack.Inflate (-BorderWidth / 2);
+
+                       Background.SetAsSource (gr, rBack);
+                       CairoHelpers.CairoRectangle(gr, rBack, CornerRadius);
+                       gr.Fill ();
+
+                       double bw = _borderWidth;
+                       double crad = CornerRadius;
+
+                       if (bw > 0) {
+                               if (BorderStyle == BorderStyle.Normal)
+                                       Foreground.SetAsSource (gr, rBack);
+                               else {
+                                       if (BorderStyle == BorderStyle.Sunken)
+                                               gr.SetSourceColor (raisedColor);
+                                       else
+                                               gr.SetSourceColor (sunkenColor);
+
+                                       CairoHelpers.CairoRectangle (gr, rBack, crad, bw);
+
+                                       if (BorderStyle == BorderStyle.Sunken)
+                                               gr.SetSourceColor (sunkenColor);
+                                       else
+                                               gr.SetSourceColor (raisedColor);
+
+                                       bw /= 2.0;
+                                       rBack.Width -= (int)Math.Round(bw);
+                                       rBack.Height -= (int)Math.Round(bw);
+                               }
+
+                               CairoHelpers.CairoRectangle (gr, rBack, crad, bw);
+                       }
+               }
+               #endregion
+       }
+}
+
diff --git a/Crow/src/Widgets/Button.cs b/Crow/src/Widgets/Button.cs
new file mode 100644 (file)
index 0000000..8b15c2e
--- /dev/null
@@ -0,0 +1,108 @@
+//
+// Button.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.Collections.Generic;
+using System.Linq;
+using System.Text;
+//using OpenTK.Graphics.OpenGL;
+
+using System.Diagnostics;
+
+using System.Xml.Serialization;
+using Crow.Cairo;
+using System.ComponentModel;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated button control
+       /// </summary>
+    public class Button : TemplatedContainer
+    {
+               #region CTOR
+               protected Button() : base() {}
+               public Button (Interface iface) : base(iface){}
+               #endregion
+
+               string image;
+               bool isPressed;
+
+               public event EventHandler Pressed;
+               public event EventHandler Released;
+
+               #region GraphicObject Overrides
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       IsPressed = true;
+
+                       base.onMouseDown (sender, e);
+
+                       //TODO:remove
+                       NotifyValueChanged ("State", "pressed");
+               }
+               public override void onMouseUp (object sender, MouseButtonEventArgs e)
+               {
+                       IsPressed = false;
+
+                       base.onMouseUp (sender, e);
+
+                       //TODO:remove
+                       NotifyValueChanged ("State", "normal");
+               }
+               #endregion
+
+               [DefaultValue("#Crow.Images.button.svg")]
+               public string Image {
+                       get { return image; }
+                       set {
+                               if (image == value)
+                                       return;
+                               image = value;
+                               NotifyValueChanged ("Image", image);
+                       }
+               }
+               [DefaultValue(false)]
+               public bool IsPressed
+               {
+                       get { return isPressed; }
+                       set
+                       {
+                               if (isPressed == value)
+                                       return;
+
+                               isPressed = value;
+
+                               NotifyValueChanged ("IsPressed", isPressed);
+
+                               if (isPressed)
+                                       Pressed.Raise (this, null);
+                               else
+                                       Released.Raise (this, null);
+                       }
+               }
+       }
+}
diff --git a/Crow/src/Widgets/CheckBox.cs b/Crow/src/Widgets/CheckBox.cs
new file mode 100644 (file)
index 0000000..7dc2b07
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// CheckBox.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.ComponentModel;
+using System.Xml.Serialization;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated checkbox control
+       /// </summary>
+       public class CheckBox : TemplatedControl
+       {
+               #region CTOR
+               protected CheckBox() : base(){}
+               public CheckBox (Interface iface) : base(iface){}
+               #endregion
+
+               bool isChecked;
+
+               public event EventHandler Checked;
+               public event EventHandler Unchecked;
+
+               [DefaultValue(false)]
+               public bool IsChecked
+               {
+                       get { return isChecked; }
+                       set
+                       {
+                               if (isChecked == value)
+                                       return;
+
+                               isChecked = value;
+
+                               NotifyValueChanged ("IsChecked", value);
+
+                               if (isChecked)
+                                       Checked.Raise (this, null);
+                               else
+                                       Unchecked.Raise (this, null);
+                       }
+               }
+
+               public override void onMouseClick (object sender, MouseButtonEventArgs e)
+               {
+                       IsChecked = !IsChecked;
+                       base.onMouseClick (sender, e);
+               }
+       }
+}
diff --git a/Crow/src/Widgets/ColorPicker.cs b/Crow/src/Widgets/ColorPicker.cs
new file mode 100644 (file)
index 0000000..9283771
--- /dev/null
@@ -0,0 +1,228 @@
+//
+// ColorPicker.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated color selector control
+       /// </summary>
+       public class ColorPicker : TemplatedControl
+       {
+               #region CTOR
+               protected ColorPicker() : base(){}
+               public ColorPicker (Interface iface) : base(iface){}
+               #endregion
+
+               const double div = 255.0;
+               const double colDiv = 1.0 / div;
+
+               Color curColor;
+               double h,s,v;
+
+               
+               public virtual double R {
+                       get { return Math.Round(curColor.R * div); }
+                       set {
+                               if (R == value)
+                                       return;
+                               curColor.R = value * colDiv;
+                               NotifyValueChanged ("R", R);
+                               hsvFromRGB ();
+                               notifyCurColorHasChanged ();
+                       }
+               }
+               
+               public virtual double G {
+                       get { return Math.Round(curColor.G * div); }
+                       set {
+                               if (G == value)
+                                       return;
+                               curColor.G = value * colDiv;
+                               NotifyValueChanged ("G", G);
+                               notifyCurColorHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               
+               public virtual double B {
+                       get { return Math.Round(curColor.B * div); }
+                       set {
+                               if (B == value)
+                                       return;
+                               curColor.B = value * colDiv;
+                               NotifyValueChanged ("B", B);
+                               notifyCurColorHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               
+               public virtual double A {
+                       get { return Math.Round(curColor.A * div); }
+                       set {
+                               if (A == value)
+                                       return;
+                               curColor.A = value * colDiv;
+                               NotifyValueChanged ("A", A);
+                               notifyCurColorHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               
+               public virtual double H {
+                       get { return Math.Round (h, 3); }
+                       set {
+                               if (H == value)
+                                       return;
+                               h = value;
+                               NotifyValueChanged ("H", H);
+                               rgbFromHSV ();
+                       }
+               }
+               
+               public virtual double S {
+                       get { return Math.Round (s, 2); }
+                       set {
+                               if (s == value)
+                                       return;
+                               s = value;
+                               NotifyValueChanged ("S", S);
+                               rgbFromHSV ();
+                       }
+               }
+               
+               public virtual double V {
+                       get { return Math.Round (v, 2); }
+                       set {
+                               if (v == value)
+                                       return;
+                               v = value;
+                               NotifyValueChanged ("V", V);
+                               rgbFromHSV ();
+                       }
+               }
+
+               
+               public virtual Fill SelectedColor {
+                       get { return new SolidColor(curColor); }
+                       set {
+                               if (value == null)
+                                       curColor = Color.White;
+                               else if (value is SolidColor) {
+                                       Color c = (value as SolidColor).color;
+                                       if (curColor == c)
+                                               return;
+                                       curColor = c;
+                               }
+                               notifyCurColorHasChanged ();
+                               notifyRGBAHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               
+               public virtual Color SelectedRawColor {
+                       get { return curColor; }
+                       set {
+                               if (curColor == value)
+                                       return;
+                               curColor = value;
+                               notifyCurColorHasChanged ();
+                               notifyRGBAHasChanged ();
+                               hsvFromRGB ();
+                       }
+               }
+               void notifyCurColorHasChanged(){
+                       NotifyValueChanged ("SelectedColor", SelectedColor);
+                       NotifyValueChanged ("SelectedRawColor", curColor);
+                       string n = curColor.ToString ();
+                       if (char.IsLetter(n[0]))
+                               NotifyValueChanged ("SelectedColorName", n);
+                       else
+                               NotifyValueChanged ("SelectedColorName", "-");
+                       string tmp = ((int)Math.Round (R)).ToString ("X2") +
+                                    ((int)Math.Round (G)).ToString ("X2") +
+                                    ((int)Math.Round (B)).ToString ("X2");
+                       if (curColor.A < 1.0)
+                               tmp += ((int)Math.Round (A)).ToString ("X2");
+                       NotifyValueChanged ("HexColor", tmp);
+               }
+               void notifyRGBAHasChanged(){
+                       NotifyValueChanged ("R", R);
+                       NotifyValueChanged ("G", G);
+                       NotifyValueChanged ("B", B);
+                       NotifyValueChanged ("A", A);
+               }
+               void notifyHSVHasChanged(){
+                       NotifyValueChanged ("H", H);
+                       NotifyValueChanged ("S", S);
+                       NotifyValueChanged ("V", V);
+               }
+               void hsvFromRGB(){
+                       Color c = curColor;
+                       c.ResetName ();
+                       double min = Math.Min (c.R, Math.Min (c.G, c.B));       //Min. value of RGB
+                       double max = Math.Max (c.R, Math.Max (c.G, c.B));       //Max. value of RGB
+                       double diff = max - min;                                                        //Delta RGB value
+
+                       v = max;
+
+                       if ( diff == 0 )//This is a gray, no chroma...
+                       {
+                               h = 0;
+                               s = 0;
+                       }else{//Chromatic data...
+                               s = diff / max;
+
+                               double diffR = (((max - c.R) / 6.0) + (diff / 2.0)) / diff;
+                               double diffG = (((max - c.G) / 6.0) + (diff / 2.0)) / diff;
+                               double diffB = (((max - c.B) / 6.0) + (diff / 2.0)) / diff;
+
+                               if (c.R == max)
+                                       h = diffB - diffG;
+                               else if (c.G == max)
+                                       h = (1.0 / 3.0) + diffR - diffB;
+                               else if (c.B == max)
+                                       h = (2.0 / 3.0) + diffG - diffR;
+
+                               if (h < 0)
+                                       h += 1;
+                               if (h > 1)
+                                       h -= 1;
+
+                       }
+                       notifyHSVHasChanged ();
+               }
+               void rgbFromHSV(){
+                       curColor = Color.FromHSV (h, v, s, curColor.A);
+                       notifyCurColorHasChanged ();
+                       notifyRGBAHasChanged ();
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/ColorSelector.cs b/Crow/src/Widgets/ColorSelector.cs
new file mode 100644 (file)
index 0000000..dea2b48
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+       /// <summary>
+       /// simple squarred rgb color selector
+       /// </summary>
+       [DesignIgnore]
+       public class ColorSelector : Widget
+       {
+               #region CTOR
+               protected ColorSelector() : base(){}
+               public ColorSelector (Interface iface) : base(iface){}
+               #endregion
+
+               protected Point mousePos;
+
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseMove (sender, e);
+                       if (IFace.Mouse.LeftButton == ButtonState.Released)
+                               return;
+                       updateMouseLocalPos (e.Position);
+               }
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseDown (sender, e);
+                       if (e.Button == MouseButton.Left)
+                               updateMouseLocalPos (e.Position);
+               }
+
+               protected virtual void updateMouseLocalPos(Point mPos){
+                       Rectangle r = ScreenCoordinates (Slot);
+                       Rectangle cb = ClientRectangle;
+                       mousePos = mPos - r.Position;
+
+                       mousePos.X = Math.Max(cb.X, mousePos.X);
+                       mousePos.X = Math.Min(cb.Right, mousePos.X);
+                       mousePos.Y = Math.Max(cb.Y, mousePos.Y);
+                       mousePos.Y = Math.Min(cb.Bottom, mousePos.Y);
+
+                       RegisterForRedraw ();
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/ColorSlider.cs b/Crow/src/Widgets/ColorSlider.cs
new file mode 100644 (file)
index 0000000..84e688e
--- /dev/null
@@ -0,0 +1,284 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.ComponentModel;
+using Crow.Cairo;
+
+namespace Crow
+{
+       /// <summary>
+       /// Color component slider with background gradient ranging from 0 to 1 for this component value.
+       /// </summary>
+       [DesignIgnore]
+       public class ColorSlider : Widget
+       {
+               #region CTOR
+               protected ColorSlider() : base(){}
+               public ColorSlider (Interface iface) : base(iface){}
+               #endregion
+
+               protected Point mousePos;//store local mouse pos sync with currentValue
+               Orientation orientation;
+               CursorType cursorType = CursorType.Pentagone;
+               ColorComponent component;
+               Color currentColor = Color.Black;
+               double currentValue = -1;//force notify for property less binding 'CurrentValue'
+
+               [DefaultValue (Orientation.Horizontal)]
+               public Orientation Orientation {
+                       get => orientation;
+                       set {
+                               if (orientation == value)
+                                       return;
+                               orientation = value;
+                               NotifyValueChanged ("Orientation", orientation);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               [DefaultValue (CursorType.Pentagone)]
+               public CursorType CursorType {
+                       get => cursorType;
+                       set {
+                               if (cursorType == value)
+                                       return;
+                               cursorType = value;
+                               NotifyValueChanged ("CursorType", cursorType);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue (ColorComponent.Value)]
+               public ColorComponent Component {
+                       get => component;
+                       set {
+                               if (component == value)
+                                       return;
+                               component = value;
+                               NotifyValueChanged ("Component", component);
+                               RegisterForRedraw ();
+                       }
+               }
+               public Color CurrentColor {
+                       get => currentColor;
+                       set {
+                               if (currentColor == value)
+                                       return;
+
+                               currentColor = value;
+
+                               NotifyValueChanged ("CurrentColor", currentColor);
+                               RegisterForRedraw ();
+
+                               switch (component) {
+                               case ColorComponent.Red:
+                                       if (currentValue == currentColor.R)
+                                               return;
+                                       currentValue = currentColor.R;
+                                       break;
+                               case ColorComponent.Green:
+                                       if (currentValue == currentColor.G)
+                                               return; 
+                                       currentValue = currentColor.G;
+                                       break;
+                               case ColorComponent.Blue:
+                                       if (currentValue == currentColor.B)
+                                               return;
+                                       currentValue = currentColor.B;
+                                       break;
+                               case ColorComponent.Alpha:
+                                       if (currentValue == currentColor.A)
+                                               return;
+                                       currentValue = currentColor.A;
+                                       break;
+                               case ColorComponent.Hue:
+                                       if (currentValue == currentColor.Hue)
+                                               return;
+                                       currentValue = currentColor.Hue;
+                                       break;
+                               case ColorComponent.Saturation:
+                                       if (currentValue == currentColor.Saturation)
+                                               return;
+                                       currentValue = currentColor.Saturation;
+                                       break;
+                               case ColorComponent.Value:
+                                       if (currentValue == currentColor.Value)
+                                               return; 
+                                       currentValue = currentColor.Value;
+                                       break;
+                               }
+
+                               NotifyValueChanged ("CurrentValue", $"{currentValue:0.000}");
+
+                               if (Orientation == Orientation.Horizontal)
+                                       mousePos.X = (int)Math.Floor (currentValue * ClientRectangle.Width);
+                               else
+                                       mousePos.Y = (int)Math.Floor (currentValue * ClientRectangle.Height);                                   
+                       }
+               }
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseMove (sender, e);
+                       if (IFace.Mouse.LeftButton == ButtonState.Released)
+                               return;
+                       updateMouseLocalPos (e.Position);
+               }
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseDown (sender, e);
+                       if (e.Button == MouseButton.Left)
+                               updateMouseLocalPos (e.Position);
+               }
+
+               protected override void onDraw (Context gr) {
+                       base.onDraw (gr);
+
+                       RectangleD r = ClientRectangle;
+                       r.Height -= 4;
+                       r.Y += 2;
+
+                       Gradient.Type gt = Gradient.Type.Horizontal;
+                       if (Orientation == Orientation.Vertical)
+                               gt = Gradient.Type.Vertical;
+
+                       Gradient grad = new Gradient (gt);
+                       Color c = currentColor;
+
+                       switch (component) {
+                       case ColorComponent.Red:
+                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (0, c.G, c.B, c.A)));
+                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, c.G, c.B, c.A)));
+                               break;
+                       case ColorComponent.Green:
+                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (c.R, 0, c.B, c.A)));
+                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (c.R, 1, c.B, c.A)));
+                               break;
+                       case ColorComponent.Blue:
+                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (c.R, c.G, 0, c.A)));
+                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (c.R, c.G, 1, c.A)));
+                               break;
+                       case ColorComponent.Alpha:
+                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (c.R, c.G, c.B, 0)));
+                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (c.R, c.G, c.B, 1)));
+                               break;
+                       case ColorComponent.Hue:
+                               grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 0, 0, 1)));
+                               grad.Stops.Add (new Gradient.ColorStop (0.167, new Color (1, 1, 0, 1)));
+                               grad.Stops.Add (new Gradient.ColorStop (0.333, new Color (0, 1, 0, 1)));
+                               grad.Stops.Add (new Gradient.ColorStop (0.5, new Color (0, 1, 1, 1)));
+                               grad.Stops.Add (new Gradient.ColorStop (0.667, new Color (0, 0, 1, 1)));
+                               grad.Stops.Add (new Gradient.ColorStop (0.833, new Color (1, 0, 1, 1)));
+                               grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, 0, 0, 1)));
+                               break;
+                       case ColorComponent.Saturation:
+                               grad.Stops.Add (new Gradient.ColorStop (0, Color.FromHSV (c.Hue, c.Value, 0.0, c.A)));
+                               grad.Stops.Add (new Gradient.ColorStop (1, Color.FromHSV (c.Hue, c.Value, 1.0, c.A)));
+                               break;
+                       case ColorComponent.Value:
+                               grad.Stops.Add (new Gradient.ColorStop (0, Color.FromHSV (c.Hue, 0.0, c.Saturation, c.A)));
+                               grad.Stops.Add (new Gradient.ColorStop (1, Color.FromHSV (c.Hue, 1.0, c.Saturation, c.A)));
+                               break;
+                       }
+
+                       grad.SetAsSource (gr, r);
+                       CairoHelpers.CairoRectangle (gr, r, CornerRadius);
+                       gr.Fill ();
+
+                       r = ClientRectangle;
+
+                       switch (cursorType) {
+                       case CursorType.Rectangle:
+                               if (Orientation == Orientation.Horizontal) {
+                                       r.Width = 5;
+                                       r.X = mousePos.X - 2.5;
+                               } else {
+                                       r.Height = 5;
+                                       r.Y = mousePos.Y - 2.5;
+                               }
+                               CairoHelpers.CairoRectangle (gr, r, 1);
+                               break;
+                       case CursorType.Circle:
+                               if (Orientation == Orientation.Horizontal)
+                                       gr.Arc (mousePos.X, r.Center.Y, 3.5, 0, Math.PI * 2.0);
+                               else
+                                       gr.Arc (r.Center.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
+                               break;
+                       case CursorType.Pentagone:
+                               if (Orientation == Orientation.Horizontal) {
+                                       r.Width = 5;
+                                       r.X = mousePos.X - 2.5;
+                                       double y = r.CenterD.Y - r.Height * 0.2;
+                                       gr.MoveTo (mousePos.X, y);
+                                       y += r.Height * 0.15;
+                                       gr.LineTo (r.Right, y);
+                                       gr.LineTo (r.Right, r.Bottom - 0.5);
+                                       gr.LineTo (r.Left, r.Bottom - 0.5);
+                                       gr.LineTo (r.Left, y);
+                                       gr.ClosePath ();
+                               } else {
+                               }
+                               break;
+                       }
+
+                       gr.SetSourceColor (Color.Black);
+                       gr.LineWidth = 2.0;
+                       gr.StrokePreserve ();
+                       gr.SetSourceColor (Color.White);
+                       gr.LineWidth = 1.0;
+                       gr.Stroke ();
+               }
+               public override void OnLayoutChanges (LayoutingType layoutType) {
+                       base.OnLayoutChanges (layoutType);
+
+                       if (Orientation == Orientation.Horizontal) {
+                               if (layoutType == LayoutingType.Width)
+                                       mousePos.X = (int)Math.Floor (currentValue * ClientRectangle.Width);
+                       } else if (layoutType == LayoutingType.Height)
+                               mousePos.Y = (int)Math.Floor (currentValue * ClientRectangle.Height);
+               }
+
+               protected virtual void updateMouseLocalPos(Point mPos){
+                       Rectangle r = ScreenCoordinates (Slot);
+                       Rectangle cb = ClientRectangle;
+                       mousePos = mPos - r.Position;
+
+                       mousePos.X = Math.Max(cb.X, mousePos.X);
+                       mousePos.X = Math.Min(cb.Right, mousePos.X);
+                       mousePos.Y = Math.Max(cb.Y, mousePos.Y);
+                       mousePos.Y = Math.Min(cb.Bottom, mousePos.Y);
+
+                       if (Orientation == Orientation.Horizontal)
+                               currentValue = (double)mousePos.X / ClientRectangle.Width;
+                       else
+                               currentValue = (double)mousePos.Y / ClientRectangle.Height;
+
+                       NotifyValueChanged ("CurrentValue", $"{currentValue:0.000}");
+
+                       Color c = currentColor;
+                       switch (component) {
+                       case ColorComponent.Red:
+                               CurrentColor = new Color(currentValue, c.G, c.B, c.A);
+                               break;
+                       case ColorComponent.Green:
+                               CurrentColor = new Color (c.R, currentValue, c.B, c.A);
+                               break;
+                       case ColorComponent.Blue:
+                               CurrentColor = new Color (c.R, c.G, currentValue, c.A);
+                               break;
+                       case ColorComponent.Alpha:
+                               CurrentColor = new Color (c.R, c.G, c.B, currentValue);
+                               break;
+                       case ColorComponent.Hue:
+                               CurrentColor = Color.FromHSV (currentValue, c.Value, c.Saturation, c.A);
+                               break;
+                       case ColorComponent.Saturation:
+                               CurrentColor = Color.FromHSV (c.Hue, c.Value, currentValue, c.A);
+                               break;
+                       case ColorComponent.Value:
+                               CurrentColor = Color.FromHSV (c.Hue, currentValue, c.Saturation, c.A);
+                               break;
+                       }
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/ComboBox.cs b/Crow/src/Widgets/ComboBox.cs
new file mode 100644 (file)
index 0000000..6122705
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// ComboBox.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.Xml.Serialization;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated control for selecting value in a pop up list
+       /// </summary>
+       public class ComboBox : ListBox
+    {
+               #region CTOR
+               protected ComboBox() : base(){}
+               public ComboBox (Interface iface) : base(iface){}
+               #endregion
+
+               Size minimumPopupSize = "10,10";
+               [XmlIgnore]public Size MinimumPopupSize{
+                       get { return minimumPopupSize; }
+                       set {
+                               minimumPopupSize = value;
+                               NotifyValueChanged ("MinimumPopupSize", minimumPopupSize);
+                       }
+               }
+
+               public override void OnLayoutChanges (LayoutingType layoutType)
+               {
+                       base.OnLayoutChanges (layoutType);
+
+                       if (layoutType == LayoutingType.Width)
+                               MinimumPopupSize = new Size (this.Slot.Width, minimumPopupSize.Height);                 
+               }
+       }
+}
diff --git a/Crow/src/Widgets/Container.cs b/Crow/src/Widgets/Container.cs
new file mode 100644 (file)
index 0000000..ce54514
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Container.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.Xml.Serialization;
+using System.Reflection;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading;
+
+namespace Crow
+{
+       /// <summary>
+       /// simple container accepting one child
+       /// </summary>
+    public class Container : PrivateContainer
+    {
+               #if DESIGN_MODE
+               public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem)
+               {
+                       if (this.design_isTGItem)
+                               return;
+                       base.getIML (doc, parentElem);
+                       if (child == null)
+                               return;
+                       child.getIML (doc, parentElem.LastChild);
+               }
+               #endif
+
+               #region CTOR
+               protected Container() : base(){}
+               public Container (Interface iface) : base(iface){}
+               #endregion
+
+               [XmlIgnore]public Widget Child {
+                       get { return child; }
+                       set { base.SetChild(value); }
+               }
+               /// <summary>
+               /// override this to handle specific steps in child addition in derived class,
+               /// and don't forget to call the base.SetChild
+               /// </summary>
+               public new virtual void SetChild(Widget _child)
+               {
+                       base.SetChild (_child);
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/DataSourceChangeEventArgs.cs b/Crow/src/Widgets/DataSourceChangeEventArgs.cs
new file mode 100644 (file)
index 0000000..a251935
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// DataSourceChangeEventArgs.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;
+
+namespace Crow
+{
+       public class DataSourceChangeEventArgs : EventArgs
+       {
+               public object OldDataSource;
+               public object NewDataSource;
+
+               public DataSourceChangeEventArgs (object oldDataSource, object newDataSource) : base()
+               {
+                       OldDataSource = oldDataSource;
+                       NewDataSource = newDataSource;
+               }
+               public override string ToString ()
+               {
+                       return string.Format ("DSChangeEA: {0} => {1}", OldDataSource, NewDataSource);
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/DirectoryView.cs b/Crow/src/Widgets/DirectoryView.cs
new file mode 100644 (file)
index 0000000..b021789
--- /dev/null
@@ -0,0 +1,136 @@
+//
+// DirectoryView.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.Xml.Serialization;
+using System.ComponentModel;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated directory viewer
+       /// </summary>
+       public class DirectoryView : TemplatedControl
+       {
+               #region CTOR
+               protected DirectoryView() : base(){}
+               public DirectoryView (Interface iface) : base(iface){}
+               #endregion
+
+               #region events
+               public event EventHandler<SelectionChangeEventArgs> SelectedItemChanged;
+               #endregion
+
+               string currentDirectory = "/";
+               bool showFiles, showHidden;
+               string fileMask = "*.*";
+
+               object _selectedItem;
+               [XmlIgnore]public object SelectedItem {
+                       get {
+                               return _selectedItem;
+                       }
+                       set { 
+                               if (value == _selectedItem)
+                                       return;
+                               _selectedItem = value;
+                               NotifyValueChanged ("SelectedItem", _selectedItem);
+                       }
+               }
+               [DefaultValue(true)]
+               public virtual bool ShowFiles {
+                       get { return showFiles; }
+                       set {
+                               if (showFiles == value)
+                                       return;
+                               showFiles = value;
+                               NotifyValueChanged ("ShowFiles", showFiles);
+                               NotifyValueChanged ("FileSystemEntries", FileSystemEntries);
+                       }
+               }
+               [DefaultValue(false)]
+               public virtual bool ShowHidden {
+                       get { return showHidden; }
+                       set {
+                               if (showHidden == value)
+                                       return;
+                               showHidden = value;
+                               NotifyValueChanged ("ShowHidden", showHidden);
+                               NotifyValueChanged ("FileSystemEntries", FileSystemEntries);
+                       }
+               }
+               [DefaultValue("*.*")]
+               public virtual string FileMask {
+                       get { return fileMask; }
+                       set {
+                               if (fileMask == value)
+                                       return;
+                               fileMask = value;
+                               NotifyValueChanged ("FileMask", fileMask);
+                               NotifyValueChanged ("FileSystemEntries", FileSystemEntries);
+                       }
+               }
+               [DefaultValue("/")]
+               public virtual string CurrentDirectory {
+                       get { return currentDirectory; }
+                       set {
+                               if (currentDirectory == value)
+                                       return;
+                               currentDirectory = value;
+                               NotifyValueChanged ("CurrentDirectory", currentDirectory);
+                               NotifyValueChanged ("FileSystemEntries", FileSystemEntries);
+                       }
+               }
+               [XmlIgnore]public FileSystemInfo[] FileSystemEntries {
+                       get {
+                               try {
+                                       if (string.IsNullOrEmpty(CurrentDirectory))
+                                               return null;
+                                       DirectoryInfo di = new DirectoryInfo(CurrentDirectory);
+                                       List<FileSystemInfo> fi = new List<FileSystemInfo> (di.GetDirectories());
+                                       if (showFiles && !string.IsNullOrEmpty(fileMask))
+                                               fi.AddRange(di.GetFiles(fileMask));
+                                       return showHidden ?
+                                               fi.ToArray() :
+                                               fi.Where(f=>!f.Attributes.HasFlag (FileAttributes.Hidden)).ToArray();
+                               } catch (Exception ex) {
+                                       Console.WriteLine (ex.ToString ());
+                                       return null;
+                               }
+                       }
+               }
+               public void onSelectedItemChanged (object sender, SelectionChangeEventArgs e){
+                       if (e.NewValue == SelectedItem)
+                               return;
+                       SelectedItem = e.NewValue;
+                       SelectedItemChanged.Raise (this, e);
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/DockStack.cs b/Crow/src/Widgets/DockStack.cs
new file mode 100644 (file)
index 0000000..a52c7f6
--- /dev/null
@@ -0,0 +1,473 @@
+//
+// DockStack.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 Crow.IML;
+using System.Linq;
+using System.Text;
+using System.IO;
+
+namespace Crow
+{
+       [DesignIgnore]
+       public class DockStack : GenericStack
+       {               
+               #region CTor
+               public DockStack ()     {}
+               public DockStack (Interface iface) : base (iface) {}
+               #endregion
+
+               /*static int color = 10;
+
+               protected override void onInitialized (object sender, EventArgs e)
+               {
+                       base.onInitialized (sender, e);
+                       Background = Color.ColorDic.Values.ToList()[color++];
+               }*/
+               public override void AddChild (Widget g)
+               {
+                       base.AddChild (g);
+                       if (localLogicalParentIsNull)
+                               g.LogicalParent = this;
+                       else
+                               g.LogicalParent = this.LogicalParent;
+               }
+               public override void InsertChild (int idx, Widget g)
+               {
+                       base.InsertChild (idx, g);
+                       g.LogicalParent = this.LogicalParent;
+               }
+
+               public override bool PointIsIn (ref Point m)
+               {                       
+                       if (!base.PointIsIn(ref m))
+                               return false;
+
+                       Group p = Parent as Group;
+                       if (p != null) {
+                               childrenRWLock.EnterReadLock ();
+                               for (int i = p.Children.Count - 1; i >= 0; i--) {
+                                       if (p.Children [i] == this)
+                                               break;
+                                       if (p.Children [i].IsDragged)
+                                               continue;
+                                       if (p.Children [i].Slot.ContainsOrIsEqual (m)) {
+                                               childrenRWLock.ExitReadLock ();
+                                               return false;
+                                       }
+                               }
+                               childrenRWLock.ExitReadLock ();
+                       }
+
+                       return Slot.ContainsOrIsEqual(m);
+               }
+
+//             public override void OnLayoutChanges (LayoutingType layoutType)
+//             {
+//                     base.OnLayoutChanges (layoutType);
+//
+//                     if ((layoutType & LayoutingType.Sizing) > 0)
+//                             computeRects();                 
+//             }
+
+               Rectangle rIn = default(Rectangle);
+               double dockThresh = 0.2;
+               Widget focusedChild;
+               internal Widget stretchedChild;
+
+               void getFocusedChild (Point lm) {
+                       Rectangle cb = ClientRectangle;
+
+                       childrenRWLock.EnterReadLock ();
+                       foreach (Widget c in Children) {
+                               Rectangle bounds = c.Slot + cb.Position;
+                               if (!bounds.ContainsOrIsEqual (lm))
+                                       continue;
+                               rIn = bounds;
+                               focusedChild = c;
+                               break;
+                       }
+                       childrenRWLock.ExitReadLock ();                 
+               }
+
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       if (IsDropTarget) {                             
+                               DockWindow dw = IFace.DragAndDropOperation.DragSource as DockWindow;
+                               if (dw == null || dw.IsDocked) {
+                                       base.onMouseMove (sender, e);
+                                       return;
+                               }
+
+                               Alignment curDockPos = dw.DockingPosition;
+                               dw.DockingPosition = Alignment.Undefined;
+
+                               Rectangle cb = ClientRectangle;
+                               Point lm = ScreenPointToLocal (e.Position);
+
+                               if (Children.Count == 0) {
+                                       Rectangle r = cb;
+                                       r.Inflate (r.Width / -5, r.Height / -5);
+                                       if (r.ContainsOrIsEqual(lm))
+                                               dw.DockingPosition = Alignment.Center;
+                               } else {
+                                       rIn = cb;
+
+                                       if (Orientation == Orientation.Horizontal || Children.Count == 1) {
+                                               if (lm.Y > cb.Top + cb.Height / 3 && lm.Y < cb.Bottom - cb.Height / 3) {
+                                                       if (lm.X < cb.Left + cb.Width / 3)
+                                                               dw.DockingPosition = Alignment.Left;
+                                                       else if (lm.X > cb.Right - cb.Width / 3)
+                                                               dw.DockingPosition = Alignment.Right;                                                   
+                                               } else {
+                                                       getFocusedChild (lm);
+                                                       if (focusedChild != null) {
+                                                               if (lm.Y < rIn.Top + rIn.Height / 3)
+                                                                       dw.DockingPosition = Alignment.Top;
+                                                               else if (lm.Y > rIn.Bottom - rIn.Height / 3)
+                                                                       dw.DockingPosition = Alignment.Bottom;                                                                          
+                                                       }
+                                               }
+                                       }
+                                       if (Orientation == Orientation.Vertical || Children.Count == 1) {
+                                               if (lm.X > cb.Left + cb.Width / 3 && lm.X < cb.Right - cb.Width / 3) {
+                                                       if (lm.Y < cb.Top + cb.Height / 3)
+                                                               dw.DockingPosition = Alignment.Top;
+                                                       else if (lm.Y > cb.Bottom - cb.Height / 3)
+                                                               dw.DockingPosition = Alignment.Bottom;                                                  
+                                               } else {
+                                                       getFocusedChild (lm);
+                                                       if (focusedChild != null) {
+                                                               if (lm.X < rIn.Left + rIn.Width / 3)
+                                                                       dw.DockingPosition = Alignment.Left;
+                                                               else if (lm.X > rIn.Right - rIn.Width / 3)
+                                                                       dw.DockingPosition = Alignment.Right;                                                                           
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if (curDockPos != dw.DockingPosition)
+                                       RegisterForGraphicUpdate ();
+                       }
+                       base.onMouseMove (sender, e);
+               }
+
+               protected override void onDragEnter (object sender, DragDropEventArgs e)
+               {
+                       base.onDragEnter (sender, e);
+                       RegisterForGraphicUpdate ();
+               }
+               protected override void onDragLeave (object sender, DragDropEventArgs e)
+               {
+                       DockWindow dw = e.DragSource as DockWindow;
+                       //if (dw != null)
+                       //      dw.DockingPosition = Alignment.Undefined;
+                       base.onDragLeave (sender, e);
+                       RegisterForGraphicUpdate ();
+               }
+
+               protected override void onDraw (Cairo.Context gr)
+               {
+                       gr.Save ();
+
+                       Rectangle rBack = new Rectangle (Slot.Size);
+
+                       Background.SetAsSource (gr, rBack);
+                       CairoHelpers.CairoRectangle (gr, rBack, CornerRadius);
+                       gr.Fill ();
+
+                       if (ClipToClientRect) {
+                               //clip to client zone
+                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
+                               gr.Clip ();
+                       }
+
+                       childrenRWLock.EnterReadLock ();
+
+                       foreach (Widget g in Children)
+                               g.Paint (ref gr);                       
+
+                       childrenRWLock.ExitReadLock ();
+
+
+                       if (!IsDropTarget) {
+                               gr.Restore ();
+                               return;
+                       }
+
+                       DockWindow dw = IFace.DragAndDropOperation.DragSource as DockWindow;
+                       if (dw == null)
+                               return;
+                       if (!dw.IsDocked) {
+                               Rectangle cb = ClientRectangle;
+                               double minDim = Math.Min (cb.Width, cb.Height);
+
+                               Rectangle r = rIn;
+                               if (Children.Count <= 1 || dw.DockingPosition.GetOrientation()==Orientation )
+                                       r = cb;
+
+                               switch (dw.DockingPosition) {
+                               case Alignment.Top:
+                                       gr.Rectangle (r.Left, r.Top, r.Width, r.Height * dockThresh);
+                                       break;
+                               case Alignment.Bottom:
+                                       gr.Rectangle (r.Left, r.Bottom - r.Height * dockThresh, r.Width, r.Height * dockThresh);
+                                       break;
+                               case Alignment.Left:
+                                       gr.Rectangle (r.Left, r.Top, r.Width * dockThresh, r.Height);
+                                       break;
+                               case Alignment.Right:
+                                       gr.Rectangle (r.Right - r.Width * dockThresh, r.Top, r.Width * dockThresh, r.Height);
+                                       break;
+                               case Alignment.Center:
+                                       r.Inflate ((int)Math.Ceiling (Math.Min (r.Width, r.Height) * -0.05));
+                                       gr.Rectangle (r);
+                                       break;
+                               }
+                               gr.LineWidth = 1;
+                               gr.SetSourceRGBA (0.4, 0.4, 0.9, 0.4);
+                               gr.FillPreserve ();
+                               gr.SetSourceRGBA (0.9, 0.9, 1.0, 0.8);
+                               gr.Stroke ();
+                       }
+                       gr.Restore ();  
+               }
+                       
+               public void Dock(DockWindow dw){
+                       DockStack activeStack = this;
+
+                       if (Children.Count == 1) {
+                               Orientation = dw.DockingPosition.GetOrientation ();
+                               if (Children [0] is DockWindow) {
+                                       (Children [0] as DockWindow).DockingPosition = dw.DockingPosition.GetOpposite ();
+                               }
+                       } else if (Children.Count > 0 && dw.DockingPosition.GetOrientation () != Orientation) {
+                               activeStack = new DockStack (IFace);
+                               activeStack.Orientation = dw.DockingPosition.GetOrientation ();
+                               activeStack.Width = focusedChild.Width;
+                               activeStack.Height = focusedChild.Height;
+                               int idx = Children.IndexOf (focusedChild);
+                               RemoveChild (focusedChild);
+                               focusedChild.Height = Measure.Stretched;
+                               focusedChild.Width = Measure.Stretched;
+                               InsertChild (idx, activeStack);
+                               activeStack.AddChild (focusedChild);
+                               activeStack.stretchedChild = focusedChild;
+                               if (focusedChild is DockWindow)
+                                       (focusedChild as DockWindow).DockingPosition = dw.DockingPosition.GetOpposite ();
+                               focusedChild = null;
+                       }
+
+                       Rectangle r = ClientRectangle;
+                       int vTreshold = (int)(r.Height * dockThresh);
+                       int hTreshold = (int)(r.Width * dockThresh);
+
+                       Console.WriteLine ("Docking {0} as {2} in {1}", dw.Name, activeStack.Name, dw.DockingPosition);
+                       switch (dw.DockingPosition) {
+                       case Alignment.Top:                                             
+                               dw.Height = vTreshold;
+                               dw.Width = Measure.Stretched;
+                               activeStack.InsertChild (0, dw);
+                               activeStack.InsertChild (1, new Splitter(IFace));
+                               break;
+                       case Alignment.Bottom:
+                               dw.Height = vTreshold;
+                               dw.Width = Measure.Stretched;
+                               activeStack.AddChild (new Splitter(IFace));
+                               activeStack.AddChild (dw);
+                               break;
+                       case Alignment.Left:
+                               dw.Width = hTreshold;
+                               dw.Height = Measure.Stretched;
+                               activeStack.InsertChild (0, dw);
+                               activeStack.InsertChild (1, new Splitter(IFace));
+                               break;
+                       case Alignment.Right:
+                               dw.Width = hTreshold;
+                               dw.Height = Measure.Stretched;
+                               activeStack.AddChild (new Splitter(IFace));
+                               activeStack.AddChild (dw);
+                               break;
+                       case Alignment.Center:
+                               dw.Width = dw.Height = Measure.Stretched;
+                               AddChild (dw);
+                               stretchedChild = dw;
+                               break;
+                       }
+               }
+               public void Undock (DockWindow dw){                     
+                       int idx = Children.IndexOf(dw);
+
+                       Console.WriteLine ("undocking child index: {0} ; name={1}; pos:{2} ; childcount:{3}",idx, dw.Name, dw.DockingPosition, Children.Count);
+
+                       RemoveChild(dw);
+
+                       if (Children.Count == 0)
+                               return;
+                       
+                       if (dw.DockingPosition == Alignment.Left || dw.DockingPosition == Alignment.Top) {                              
+                               RemoveChild (idx);
+                               if (stretchedChild == dw) {
+                                       stretchedChild = Children [idx];
+                                       stretchedChild.Width = stretchedChild.Height = Measure.Stretched;
+                               }
+                       } else {
+                               RemoveChild (idx - 1);
+                               if (stretchedChild == dw) {
+                                       stretchedChild = Children [idx-2];
+                                       stretchedChild.Width = stretchedChild.Height = Measure.Stretched;
+                               }
+                       }
+
+                       if (Children.Count == 1) {
+                               DockStack dsp = Parent as DockStack;
+                               if (dsp == null) {
+                                       Children [0].Width = Children [0].Height = Measure.Stretched;
+                                       return;
+                               }                               
+                               //remove level and move remaining obj to level above
+                               Widget g = Children [0];
+                               RemoveChild (g);
+                               idx = dsp.Children.IndexOf (this);
+                               dsp.RemoveChild (this);
+                               dsp.InsertChild (idx, g);
+                               g.Width = this.Width;
+                               g.Height = this.Height;
+                               if (dsp.stretchedChild == this)
+                                       dsp.stretchedChild = g;
+                               dsp.checkAlignments ();
+                       } else
+                               checkAlignments ();
+               }
+
+               internal void checkAlignments () {
+                       DockWindow dw = Children[0] as DockWindow;
+                       if (dw != null)
+                               dw.DockingPosition = (Orientation == Orientation.Horizontal ? Alignment.Left : Alignment.Top);
+                       dw = Children[Children.Count - 1] as DockWindow;
+                       if (dw != null)
+                               dw.DockingPosition = (Orientation == Orientation.Horizontal ? Alignment.Right : Alignment.Bottom);
+               }
+
+               //read next value in config string until next ';'
+               string getConfAttrib (string conf, ref int i) {
+                       int nextI = conf.Substring (i).IndexOf (';');
+                       string tmp = conf.Substring (i, nextI);
+                       i += nextI + 1;
+                       return tmp;
+               }
+               /// <summary>
+               /// Imports the config.
+               /// </summary>
+               /// <param name="conf">Conf.</param>
+               /// <param name="dataSource">Data source for the docked windows</param>
+               public void ImportConfig (string conf, object dataSource = null) {
+                       lock (IFace.UpdateMutex) {
+                               ClearChildren ();
+                               stretchedChild = null;
+                               int i = 0;
+                               Orientation = (Orientation)Enum.Parse (typeof(Orientation), getConfAttrib (conf, ref i));
+                               importConfig (conf, ref i, dataSource);
+                       }
+               }
+               public string ExportConfig () {
+                       return Orientation.ToString() + ";" + exportConfig();
+               }
+               void importConfig (string conf, ref int i, object dataSource) {                                         
+                       if (conf [i++] != '(')
+                               return;                 
+                       while (i < conf.Length - 4) {
+                               string sc = conf.Substring (i, 4);
+                               i += 4;
+                               switch (sc) {
+                               case "WIN;":
+                                       DockWindow dw = null;
+                                       string wName = getConfAttrib (conf, ref i);
+                                       try {
+                                               dw = IFace.CreateInstance (wName) as DockWindow;        
+                                       } catch {
+                                               dw = new DockWindow (IFace);
+                                       }
+
+                                       dw.Name = wName;
+                                       dw.Width = Measure.Parse (getConfAttrib (conf, ref i));
+                                       dw.Height = Measure.Parse (getConfAttrib (conf, ref i));
+                                       dw.DockingPosition = (Alignment)Enum.Parse (typeof(Alignment), getConfAttrib (conf, ref i));
+                                       dw.savedSlot = Rectangle.Parse (getConfAttrib (conf, ref i));
+                                       dw.wasResizable = Boolean.Parse (getConfAttrib (conf, ref i));
+
+                                       dw.IsDocked = true;
+                                       dw.DataSource = dataSource;
+                                       this.AddChild (dw);
+
+                                       break;
+                               case "STK;":
+                                       DockStack ds = new DockStack (IFace);
+                                       ds.Width = Measure.Parse (getConfAttrib (conf, ref i));
+                                       ds.Height = Measure.Parse (getConfAttrib (conf, ref i));
+                                       ds.Orientation = (Orientation)Enum.Parse (typeof(Orientation), getConfAttrib (conf, ref i));
+
+                                       this.AddChild (ds);
+
+                                       ds.importConfig (conf, ref i, dataSource);
+                                       break;
+                               case "SPL;":
+                                       Splitter sp = new Splitter (IFace);
+                                       sp.Width = Measure.Parse (getConfAttrib (conf, ref i));
+                                       sp.Height = Measure.Parse (getConfAttrib (conf, ref i));
+                                       sp.Thickness = int.Parse (getConfAttrib (conf, ref i));
+                                       this.AddChild (sp);
+                                       break;
+                               }
+                               char nextC = conf [i++];
+                               if (nextC == ')')
+                                       break;
+                       }
+               }
+               string exportConfig () {
+                       StringBuilder tmp = new StringBuilder("(");
+
+                       for (int i = 0; i < Children.Count; i++) {
+                               if (Children [i] is DockWindow) {
+                                       DockWindow dw = Children [i] as DockWindow;
+                                       tmp.Append (string.Format("WIN;{0};{1};{2};{3};{4};{5};",dw.Name, dw.Width, dw.Height, dw.DockingPosition, dw.savedSlot, dw.wasResizable));
+                               } else if (Children [i] is DockStack) {
+                                       DockStack ds = Children [i] as DockStack;
+                                       tmp.Append (string.Format("STK;{0};{1};{2};{3}", ds.Width, ds.Height, ds.Orientation, ds.exportConfig()));
+                               } else if (Children [i] is Splitter) {
+                                       Splitter sp = Children [i] as Splitter;
+                                       tmp.Append (string.Format("SPL;{0};{1};{2};", sp.Width, sp.Height, sp.Thickness));
+                               }                                       
+                               if (i < Children.Count - 1)
+                                       tmp.Append ("|");                               
+                       }
+
+                       tmp.Append (")");
+                       return tmp.ToString ();
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/DockWindow.cs b/Crow/src/Widgets/DockWindow.cs
new file mode 100644 (file)
index 0000000..4be23ad
--- /dev/null
@@ -0,0 +1,175 @@
+//
+// DockingView.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.Xml.Serialization;
+
+namespace Crow
+{
+       public class DockWindow : Window
+       {
+               #region CTOR
+               public DockWindow () {}
+               public DockWindow (Interface iface) : base (iface) {}
+               #endregion
+
+               int undockThreshold = 10;
+               bool isDocked = false;
+               Alignment docking = Alignment.Undefined;
+
+               Point undockingMousePosOrig; //mouse pos when docking was donne, use for undocking on mouse move
+               internal Rectangle savedSlot;   //last undocked slot recalled when view is undocked
+               internal bool wasResizable;
+
+               public bool IsDocked {
+                       get { return isDocked; }
+                       set {
+                               if (isDocked == value)
+                                       return;
+                               isDocked = value;
+                               NotifyValueChanged ("IsDocked", isDocked);
+                               NotifyValueChanged ("IsFloating", !isDocked);
+                       }
+               }
+               [XmlIgnore] public bool IsFloating { get { return !isDocked; }}
+
+               public Alignment DockingPosition {
+                       get { return docking; }
+                       set {
+                               if (docking == value)
+                                       return;
+                               docking = value;
+                               NotifyValueChanged ("DockingPosition", DockingPosition);
+                       }
+               }
+               public override bool PointIsIn (ref Point m)
+               {                       
+                       if (!base.PointIsIn(ref m))
+                               return false;
+
+                       Group p = Parent as Group;
+                       if (p != null) {
+                               lock (p.Children) {
+                                       for (int i = p.Children.Count - 1; i >= 0; i--) {
+                                               if (p.Children [i] == this)
+                                                       break;
+                                               if (p.Children [i].IsDragged)
+                                                       continue;
+                                               if (p.Children [i].Slot.ContainsOrIsEqual (m)) {                                                
+                                                       return false;
+                                               }
+                                       }
+                               }
+                       }
+                       return Slot.ContainsOrIsEqual(m);
+               }
+
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+//                     if (this.HasFocus && e.Mouse.IsButtonDown (MouseButton.Left) && IsDocked) {
+//                             if (Math.Abs (e.Position.X - undockingMousePosOrig.X) > 10 ||
+//                                 Math.Abs (e.Position.X - undockingMousePosOrig.X) > 10)
+//                                     Undock ();
+//                     }
+
+                       if (this.HasFocus && e.Mouse.IsButtonDown (MouseButton.Left) && IsDocked)
+                               CheckUndock (e.Position);
+
+                       base.onMouseMove (sender, e);
+               }
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       e.Handled = true;
+                       base.onMouseDown (sender, e);
+
+                       if (this.HasFocus && IsDocked && e.Button == MouseButton.Left)
+                               undockingMousePosOrig = e.Position;
+               }
+               public bool CheckUndock (Point mousePos) {
+                       //if (DockingPosition == Alignment.Center)
+                       //      return false;
+                       Console.WriteLine ($"{mousePos.X},{mousePos.Y}");
+                       if (Math.Abs (mousePos.X - undockingMousePosOrig.X) < undockThreshold ||
+                           Math.Abs (mousePos.X - undockingMousePosOrig.X) < undockThreshold)
+                               return false;
+                       Undock ();
+                       return true;
+               }
+
+               protected override void onStartDrag (object sender, DragDropEventArgs e)
+               {
+                       base.onStartDrag (sender, e);
+
+                       undockingMousePosOrig = IFace.Mouse.Position;
+               }
+               protected override void onDrop (object sender, DragDropEventArgs e)
+               {
+                       if (!isDocked && DockingPosition != Alignment.Undefined && e.DropTarget is DockStack)
+                               Dock (e.DropTarget as DockStack);
+                       base.onDrop (sender, e);
+               }
+               public void Undock () {
+                       lock (IFace.UpdateMutex) {
+                               DockStack ds = Parent as DockStack;
+                               ds.Undock (this);
+
+                               IFace.AddWidget (this);
+
+                               Left = savedSlot.Left;
+                               Top = savedSlot.Top;
+                               Width = savedSlot.Width;
+                               Height = savedSlot.Height;
+
+                               IsDocked = false;
+                               DockingPosition = Alignment.Undefined;
+                               Resizable = wasResizable;
+                       }
+               }
+
+               public void Dock (DockStack target){
+                       lock (IFace.UpdateMutex) {
+                               IsDocked = true;
+                               //undockingMousePosOrig = lastMousePos;
+                               savedSlot = this.LastPaintedSlot;
+                               wasResizable = Resizable;
+                               Resizable = false;
+                               LastSlots = LastPaintedSlot = Slot = default(Rectangle);
+                               Left = Top = 0;
+
+                               IFace.RemoveWidget (this);
+
+                               target.Dock (this);
+                       }
+               }
+
+               protected override void close ()
+               {
+                       if (isDocked)
+                               Undock ();
+                       base.close ();
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/EnumSelector.cs b/Crow/src/Widgets/EnumSelector.cs
new file mode 100644 (file)
index 0000000..932e90e
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (c) 2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.ComponentModel;
+
+namespace Crow
+{
+       /// <summary>
+       /// Convenient widget for selecting value from enum
+       /// </summary>
+       public class EnumSelector : GenericStack
+       {
+               #region CTOR
+               protected EnumSelector () : base(){}
+               public EnumSelector (Interface iface) : base(iface){}
+               #endregion
+
+               #region private fields
+               Enum enumValue;
+               Type enumType;
+               #endregion
+
+               #region public properties
+               /// <summary>
+               /// use to define the colors of the 3d border
+               /// </summary>
+               [DefaultValue(null)]
+               public virtual Enum EnumValue {
+                       get { return enumValue; }
+                       set {
+                               if (enumValue == value)
+                                       return;
+
+                               enumValue = value;
+
+                               if (enumValue != null) {
+                                       if (enumType != enumValue.GetType ()) {
+                                               ClearChildren ();
+                                               enumType = enumValue.GetType ();
+                                               foreach (string en in enumType.GetEnumNames ()) {
+                                                       RadioButton rb = new RadioButton (IFace);
+                                                       rb.Caption = en;
+                                                       if (enumValue.ToString() == en)
+                                                               rb.IsChecked = true;
+                                                       rb.Checked += (sender, e) => (((RadioButton)sender).Parent as EnumSelector).EnumValue = (Enum)Enum.Parse (enumType, (sender as RadioButton).Caption);
+                                                       AddChild (rb);
+                                                       RegisterForLayouting (LayoutingType.All);
+                                               }
+                                       }
+                               } else 
+                                       ClearChildren ();
+
+                               NotifyValueChanged ("EnumValue", enumValue);
+                               RegisterForRedraw ();
+                       }
+               }
+               #endregion
+
+       }
+}
+
diff --git a/Crow/src/Widgets/Expandable.cs b/Crow/src/Widgets/Expandable.cs
new file mode 100644 (file)
index 0000000..3a480b2
--- /dev/null
@@ -0,0 +1,131 @@
+//
+// Expandable.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.ComponentModel;
+using System.Xml.Serialization;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated control whose content can be hidden and shown on demand
+       /// </summary>
+    public class Expandable : TemplatedContainer
+    {
+               #region CTOR
+               protected Expandable() : base(){}
+               public Expandable (Interface iface) : base(iface){}
+               #endregion
+
+               #region Private fields
+               bool _isExpanded;
+               string image;
+               #endregion
+
+               #region Event Handlers
+               /// <summary>
+               /// Occurs when control is expanded.
+               /// </summary>
+               public event EventHandler Expand;
+               /// <summary>
+               /// Occurs when control is collapsed.
+               /// </summary>
+               public event EventHandler Collapse;
+               #endregion
+
+               public BooleanTestOnInstance GetIsExpandable;
+
+               /// <summary>
+               /// mouse click event handler for easy expand triggering in IML
+               /// </summary>
+               public void onClickForExpand (object sender, MouseButtonEventArgs e)
+               {
+                       IsExpanded = !IsExpanded;
+               }
+
+               #region Public properties
+               [DefaultValue("#Crow.Icons.expandable.svg")]
+               public string Image {
+                       get { return image; }
+                       set {
+                               if (image == value)
+                                       return;
+                               image = value;
+                               NotifyValueChanged ("Image", image);
+                       }
+               }
+               [DefaultValue(false)]
+        public bool IsExpanded
+        {
+                       get { return _isExpanded; }
+            set
+            {
+                               if (value == _isExpanded)
+                                       return;
+
+                               _isExpanded = value;
+
+                               bool isExp = IsExpandable;
+                               NotifyValueChanged ("IsExpandable", isExp);
+                               if (!isExp)
+                                       _isExpanded = false;
+
+                               NotifyValueChanged ("IsExpanded", _isExpanded);
+
+                               if (_isExpanded)
+                                       onExpand (this, null);
+                               else
+                                       onCollapse (this, null);
+            }
+        }
+               [XmlIgnore]public bool IsExpandable {
+                       get {
+                               try {
+                                       return GetIsExpandable == null ? true : GetIsExpandable (this);
+                               } catch (Exception ex) {
+                                       System.Diagnostics.Debug.WriteLine ("Not Expandable error: " + ex.ToString ());
+                                       return false;
+                               }
+                       }
+               }
+               #endregion
+
+               public virtual void onExpand(object sender, EventArgs e)
+               {
+                       if (_contentContainer != null)
+                               _contentContainer.Visible = true;
+
+                       Expand.Raise (this, e);
+               }
+               public virtual void onCollapse(object sender, EventArgs e)
+               {
+                       if (_contentContainer != null)
+                               _contentContainer.Visible = false;
+
+                       Collapse.Raise (this, e);
+               }
+       }
+}
diff --git a/Crow/src/Widgets/FileDialog.cs b/Crow/src/Widgets/FileDialog.cs
new file mode 100644 (file)
index 0000000..db66ae9
--- /dev/null
@@ -0,0 +1,155 @@
+//
+// FileDialog.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.Xml.Serialization;
+using System.ComponentModel;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated control for selecting files
+       /// </summary>
+       public class FileDialog: Window
+       {
+               #region CTOR
+               protected FileDialog() : base(){}
+               public FileDialog (Interface iface) : base(iface){}
+               #endregion
+
+               string searchPattern, curDir, _selectedFile, _selectedDir;
+               bool showHidden, showFiles;
+
+               #region events
+               public event EventHandler OkClicked;
+               #endregion
+
+               public string SelectedFileFullPath {
+                       get { return Path.Combine (SelectedDirectory, SelectedFile); }
+               }
+               [DefaultValue("/home")]
+               public virtual string CurrentDirectory {
+                       get { return curDir; }
+                       set {
+                               if (curDir == value)
+                                       return;
+                               curDir = value;
+                               NotifyValueChanged ("CurrentDirectory", curDir);
+                               SelectedDirectory = curDir;
+                       }
+               }
+
+               [DefaultValue("*")]
+               public virtual string SearchPattern {
+                       get { return searchPattern; }
+                       set {
+                               if (searchPattern == value)
+                                       return;
+                               searchPattern = value;
+                               NotifyValueChanged ("SearchPattern", searchPattern);
+
+                       }
+               }
+               [DefaultValue(false)]
+               public virtual bool ShowHidden {
+                       get { return showHidden; }
+                       set {
+                               if (showHidden == value)
+                                       return;
+                               showHidden = value;
+                               NotifyValueChanged ("ShowHidden", showHidden);
+                       }
+               }
+               [DefaultValue(true)]
+               public virtual bool ShowFiles {
+                       get { return showFiles; }
+                       set {
+                               if (showFiles == value)
+                                       return;
+                               showFiles = value;
+                               NotifyValueChanged ("ShowFiles", showFiles);
+                       }
+               }
+               public string SelectedFile {
+                       get { return _selectedFile; }
+                       set {
+                               if (value == _selectedFile)
+                                       return;
+                               _selectedFile = value;
+                               NotifyValueChanged ("SelectedFile", _selectedFile);
+                       }
+               }
+               public string SelectedDirectory {
+                       get { return _selectedDir; }
+                       set {
+                               if (value == _selectedDir)
+                                       return;
+                               _selectedDir = value;
+                               NotifyValueChanged ("SelectedDirectory", _selectedDir);
+                       }
+               }
+
+               public void onFVSelectedItemChanged (object sender, SelectionChangeEventArgs e){
+                       if (e.NewValue != null) {
+                               if (File.GetAttributes (e.NewValue.ToString ()).HasFlag (FileAttributes.Directory)) {
+                                       SelectedDirectory = e.NewValue.ToString ();
+                                       SelectedFile = "";
+                               } else {
+                                       SelectedDirectory = Path.GetDirectoryName (e.NewValue.ToString ());
+                                       SelectedFile = Path.GetFileName (e.NewValue.ToString ());
+                               }
+                       }
+               }
+               public void onDVSelectedItemChanged (object sender, SelectionChangeEventArgs e){
+                       if (e.NewValue != null)
+                               SelectedDirectory = e.NewValue.ToString();
+               }
+               public void goUpDirClick (object sender, MouseButtonEventArgs e){
+                       string root = Directory.GetDirectoryRoot(CurrentDirectory);
+                       if (CurrentDirectory == root)
+                               return;
+                       CurrentDirectory = Directory.GetParent(CurrentDirectory).FullName;
+               }
+               void onFileSelect(object sender, MouseButtonEventArgs e){
+                       if (string.IsNullOrEmpty (SelectedFile))
+                               CurrentDirectory = SelectedDirectory;
+                       else {
+                               OkClicked.Raise (this, null);
+                               IFace.DeleteWidget (this);
+                       }
+               }
+               void onCancel(object sender, MouseButtonEventArgs e){
+                       IFace.DeleteWidget (this);
+               }
+
+       }
+}
+
diff --git a/Crow/src/Widgets/GenericStack.cs b/Crow/src/Widgets/GenericStack.cs
new file mode 100644 (file)
index 0000000..5189748
--- /dev/null
@@ -0,0 +1,252 @@
+//
+// GenericStack.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.ComponentModel;
+using System.Diagnostics;
+using System.Xml.Serialization;
+using System;
+using System.Linq;
+
+namespace Crow
+{
+       /// <summary>
+       /// group container that stacked its children horizontally or vertically
+       /// </summary>
+       public class GenericStack : Group
+    {
+               #region CTOR
+               protected GenericStack() : base(){}
+               public GenericStack(Interface iface) : base(iface){}
+               #endregion
+
+               #region Private fields
+        int _spacing;
+        Orientation _orientation;
+               #endregion
+
+               #region Public Properties
+        [DefaultValue(2)]
+        public int Spacing
+        {
+                       get { return _spacing; }
+            set { 
+                               if (_spacing == value)
+                                       return;
+                               _spacing = value; 
+                               NotifyValueChanged ("Spacing", Spacing);
+                               RegisterForLayouting (LayoutingType.Sizing|LayoutingType.ArrangeChildren);
+                       }
+        }
+        [DefaultValue(Orientation.Horizontal)]
+        public virtual Orientation Orientation
+        {
+            get { return _orientation; }
+            set { _orientation = value; }
+        }
+               #endregion
+
+               #region GraphicObject Overrides
+               public override bool ArrangeChildren { get { return true; } }
+               public override void ChildrenLayoutingConstraints (ref LayoutingType layoutType)
+               {
+                       //Prevent child repositionning in the direction of stacking
+                       if (Orientation == Orientation.Horizontal)
+                               layoutType &= (~LayoutingType.X);
+                       else
+                               layoutType &= (~LayoutingType.Y);                       
+               }
+               protected override int measureRawSize (LayoutingType lt)
+               {
+                       int totSpace = Math.Max(0, Spacing * (Children.Count (c => c.Visible) - 1));
+                       if (lt == LayoutingType.Width) {
+                               if (Orientation == Orientation.Horizontal)
+                                       return contentSize.Width + totSpace + 2 * Margin;
+                       }else if (Orientation == Orientation.Vertical)
+                               return contentSize.Height + totSpace + 2 * Margin;                                                      
+                       
+                       return base.measureRawSize (lt);
+               }
+               public virtual void ComputeChildrenPositions()
+               {
+                       int d = 0;
+                       if (Orientation == Orientation.Horizontal) {
+                               foreach (Widget c in Children) {
+                                       if (!c.Visible)
+                                               continue;
+                                       c.Slot.X = d;
+                                       d += c.Slot.Width + Spacing;
+                               }
+                       } else {
+                               foreach (Widget c in Children) {
+                                       if (!c.Visible)
+                                               continue;                                       
+                                       c.Slot.Y = d;
+                                       d += c.Slot.Height + Spacing;
+                               }
+                       }
+                       IsDirty = true;
+               }
+               Widget stretchedGO = null;
+               public override bool UpdateLayout (LayoutingType layoutType)
+        {
+                       RegisteredLayoutings &= (~layoutType);
+
+                       if (layoutType == LayoutingType.ArrangeChildren) {
+                               //allow 1 child to have size to 0 if stack has fixed or streched size policy,
+                               //this child will occupy remaining space
+                               //if stack size policy is Fit, no child may have stretch enabled
+                               //in the direction of stacking.
+                               ComputeChildrenPositions ();
+
+                               //if no layouting remains in queue for item, registre for redraw
+                               if (RegisteredLayoutings == LayoutingType.None && IsDirty)
+                                       IFace.EnqueueForRepaint (this);
+
+                               return true;
+                       }
+
+                       return base.UpdateLayout(layoutType);
+        }
+
+               void adjustStretchedGo (LayoutingType lt){
+                       if (stretchedGO == null)
+                               return;
+                       if (lt == LayoutingType.Width) {
+                               int newW = Math.Max (
+                                                  this.ClientRectangle.Width - contentSize.Width - Spacing * (Children.Count - 1),
+                                                  stretchedGO.MinimumSize.Width);
+                               if (stretchedGO.MaximumSize.Width > 0)
+                                       newW = Math.Min (newW, stretchedGO.MaximumSize.Width);
+                               if (newW != stretchedGO.Slot.Width) {                                                   
+                                       stretchedGO.Slot.Width = newW;
+                                       stretchedGO.IsDirty = true;
+                                       #if DEBUG_LAYOUTING
+                               Debug.WriteLine ("\tAdjusting Width of " + stretchedGO.ToString());
+                                       #endif
+                                       stretchedGO.LayoutChanged -= OnChildLayoutChanges;
+                                       stretchedGO.OnLayoutChanges (LayoutingType.Width);
+                                       stretchedGO.LayoutChanged += OnChildLayoutChanges;
+                                       stretchedGO.LastSlots.Width = stretchedGO.Slot.Width;
+                               }
+                       } else {
+                               int newH = Math.Max (
+                                       this.ClientRectangle.Height - contentSize.Height - Spacing * (Children.Count - 1),
+                                       stretchedGO.MinimumSize.Height);
+                               if (stretchedGO.MaximumSize.Height > 0)
+                                       newH = Math.Min (newH, stretchedGO.MaximumSize.Height);
+                               if (newH != stretchedGO.Slot.Height) {
+                                       stretchedGO.Slot.Height = newH;
+                                       stretchedGO.IsDirty = true;
+                                       #if DEBUG_LAYOUTING
+                                       Debug.WriteLine ("\tAdjusting Height of " + stretchedGO.ToString());
+                                       #endif
+                                       stretchedGO.LayoutChanged -= OnChildLayoutChanges;
+                                       stretchedGO.OnLayoutChanges (LayoutingType.Height);
+                                       stretchedGO.LayoutChanged += OnChildLayoutChanges;
+                                       stretchedGO.LastSlots.Height = stretchedGO.Slot.Height;
+                               }                               
+                       }
+               }
+
+               public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
+               {
+                       Widget go = sender as Widget;
+                       //Debug.WriteLine ("child layout change: " + go.LastSlots.ToString() + " => " + go.Slot.ToString());
+                       switch (arg.LayoutType) {
+                       case LayoutingType.Width:
+                               if (Orientation == Orientation.Horizontal) {
+                                       if (go.Width == Measure.Stretched) {
+                                               if (stretchedGO == null && Width != Measure.Fit)
+                                                       stretchedGO = go;
+                                               else if (stretchedGO != go) {
+                                                       go.Slot.Width = 0;
+                                                       go.Width = Measure.Fit;
+                                                       return;
+                                               }
+                                       } else
+                                               contentSize.Width += go.Slot.Width - go.LastSlots.Width;
+
+                                       adjustStretchedGo (LayoutingType.Width);                                        
+                                       
+                                       if (Width == Measure.Fit)
+                                               this.RegisterForLayouting (LayoutingType.Width);
+                                       
+                                       this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+                                       return;
+                               }
+                               break;
+                       case LayoutingType.Height:
+                               if (Orientation == Orientation.Vertical) {
+                                       if (go.Height == Measure.Stretched) {
+                                               if (stretchedGO == null && Height != Measure.Fit)
+                                                       stretchedGO = go;
+                                               else if (stretchedGO != go){
+                                                       go.Slot.Height = 0;
+                                                       go.Height = Measure.Fit;
+                                                       return;
+                                               }
+                                       } else
+                                               contentSize.Height += go.Slot.Height - go.LastSlots.Height;
+                                       
+                                       adjustStretchedGo (LayoutingType.Height);
+
+                                       if (Height == Measure.Fit)
+                                               this.RegisterForLayouting (LayoutingType.Height);
+
+                                       this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+                                       return;
+                               }
+                               break;
+                       }
+                       base.OnChildLayoutChanges (sender, arg);
+               }
+               #endregion
+
+       public override void RemoveChild (Widget child)
+               {
+                       if (child != stretchedGO) {
+                               if (Orientation == Orientation.Horizontal)
+                                       contentSize.Width -= child.LastSlots.Width;
+                               else 
+                                       contentSize.Height -= child.LastSlots.Height;                           
+                       }
+                       base.RemoveChild (child);
+                       if (child == stretchedGO) {
+                               stretchedGO = null;
+                               RegisterForLayouting (LayoutingType.Sizing);
+                       }else if (Orientation == Orientation.Horizontal)                                
+                               adjustStretchedGo (LayoutingType.Width);
+                       else                            
+                               adjustStretchedGo (LayoutingType.Height);                       
+               }
+
+               public override void ClearChildren ()
+               {
+                       base.ClearChildren ();
+                       stretchedGO = null;
+               }
+       }
+}
diff --git a/Crow/src/Widgets/GraduatedSlider.cs b/Crow/src/Widgets/GraduatedSlider.cs
new file mode 100644 (file)
index 0000000..71bbff1
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// GraduatedSlider.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.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crow.Cairo;
+using System.Xml.Serialization;
+
+namespace Crow
+{
+       [DesignIgnore]
+       public class GraduatedSlider : Slider
+    {     
+               #region CTOR
+               protected GraduatedSlider() : base(){}
+               public GraduatedSlider(Interface iface) : base(iface)
+               {}
+//             public GraduatedSlider(double minimum, double maximum, double step)
+//            : base()
+//        {
+//                     Minimum = minimum;
+//                     Maximum = maximum;
+//                     SmallIncrement = step;
+//                     LargeIncrement = step * 5;
+//        }
+               #endregion
+
+               protected override void DrawGraduations(Context gr, PointD pStart, PointD pEnd)
+               {
+                       Rectangle r = ClientRectangle;
+                       Foreground.SetAsSource (gr);
+
+                       gr.LineWidth = 2;
+                       gr.MoveTo(pStart);
+                       gr.LineTo(pEnd);
+
+                       gr.Stroke();
+                       gr.LineWidth = 1;
+
+                       double sst = unity * SmallIncrement;
+                       double bst = unity * LargeIncrement;
+
+
+                       PointD vBar = new PointD(0, sst);
+                       for (double x = Minimum; x <= Maximum - Minimum; x += SmallIncrement)
+                       {
+                               double lineLength = r.Height / 3;
+                               if (x % LargeIncrement != 0)
+                                       lineLength /= 3;
+                               PointD p = new PointD(pStart.X + x * unity, pStart.Y);
+                               gr.MoveTo(p);
+                               gr.LineTo(new PointD(p.X, p.Y + lineLength));
+                       }
+                       gr.Stroke();
+               }
+    }
+}
diff --git a/Crow/src/Widgets/Grid.cs b/Crow/src/Widgets/Grid.cs
new file mode 100644 (file)
index 0000000..ad776bd
--- /dev/null
@@ -0,0 +1,171 @@
+//
+// Grid.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.Diagnostics;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       /// <summary>
+       /// Simple grid container
+       /// Allow symetric placement of children on a grid,
+       /// excedental child (above grid sizing) are ignored
+       /// and invisible child keep their place in the grid
+       /// </summary>
+    public class Grid : Group
+    {
+               #region CTOR
+               protected Grid () : base(){}
+               public Grid(Interface iface) : base(iface)
+               {            
+               }
+               #endregion
+
+               #region Private fields
+        int _spacing;
+               int _columnCount;
+               int _rowCount;
+               #endregion
+
+               #region Public Properties
+        [DefaultValue(2)]
+        public int Spacing
+        {
+                       get { return _spacing; }
+            set { _spacing = value; }
+        }
+        [DefaultValue(2)]
+        public virtual int ColumnCount
+        {
+            get { return _columnCount; }
+            set { 
+                               if (_columnCount == value)
+                                       return;
+
+                               _columnCount = value; 
+
+                               NotifyValueChanged ("ColumnCount", ColumnCount);
+                               this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+                       }
+        }
+               [DefaultValue(2)]
+               public virtual int RowCount
+               {
+                       get { return _rowCount; }
+                       set { 
+                               if (_rowCount == value)
+                                       return;
+
+                               _rowCount = value; 
+
+                               NotifyValueChanged ("RowCount", RowCount);
+                               this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+                       }
+               }
+               public virtual int CaseWidth {
+                       get { return (Slot.Width - (ColumnCount - 1) * Spacing) / ColumnCount; }
+               }
+               public virtual int CaseHeight {
+                       get { return (Slot.Height - (RowCount - 1) * Spacing) / RowCount; }
+               }
+
+               #endregion
+
+               #region GraphicObject Overrides
+//             protected override Size measureRawSize ()
+//             {
+//                     Size tmp = new Size ();
+//
+//                     foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) {
+//                             tmp.Width = Math.Max (tmp.Width, c.Slot.Width);
+//                             tmp.Height = Math.Max (tmp.Height, c.Slot.Height);
+//                     }
+//
+//                     tmp.Width *= (ColumnCount - 1) * Spacing / ColumnCount;;
+//                     tmp.Height *= (RowCount - 1) * Spacing / RowCount;
+//                     tmp.Width += 2 * Margin;
+//                     tmp.Height += 2 * Margin;
+//
+//                     return tmp;
+//             }
+               public override void ChildrenLayoutingConstraints (ref LayoutingType layoutType)
+               {
+                       //Prevent child repositionning
+                       layoutType &= (~LayoutingType.Positioning);
+               }
+               public override bool ArrangeChildren { get { return true; } }
+               public virtual void ComputeChildrenPositions()
+               {
+                       int slotWidth = CaseWidth;
+                       int slotHeight = CaseHeight;
+                       for (int curY = 0; curY < RowCount; curY++) {
+                               for (int curX = 0; curX < ColumnCount; curX++) {
+                                       int idx = curY * ColumnCount + curX;
+                                       if (idx >= Children.Count)
+                                               return;
+                                       Widget c = Children [idx];
+                                       if (!c.Visible)
+                                               continue;
+                                       c.Slot.X = curX * (slotWidth + Spacing);
+                                       c.Slot.Y = curY * (slotHeight + Spacing);
+                                       //c.Slot.Width = slotWidth;
+                                       //c.Slot.Height = slotHeight;
+                               }
+                       }
+                       IsDirty = true;
+               }
+               public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
+               {
+                       //base.OnChildLayoutChanges (sender, arg);
+               }
+
+               public override bool UpdateLayout (LayoutingType layoutType)
+               {
+                       RegisteredLayoutings &= (~layoutType);
+
+                       if (layoutType == LayoutingType.ArrangeChildren) {                              
+
+                               ComputeChildrenPositions ();
+
+                               //if no layouting remains in queue for item, registre for redraw
+                               if (RegisteredLayoutings == LayoutingType.None && IsDirty)
+                                       IFace.EnqueueForRepaint (this);
+                               
+                               return true;
+                       }
+
+                       return base.UpdateLayout(layoutType);
+               }
+               #endregion
+
+    
+       }
+}
diff --git a/Crow/src/Widgets/Group.cs b/Crow/src/Widgets/Group.cs
new file mode 100644 (file)
index 0000000..a0ae35b
--- /dev/null
@@ -0,0 +1,472 @@
+//
+// Group.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.Collections.Generic;
+using System.ComponentModel;
+using System.Xml.Serialization;
+using Crow.Cairo;
+using System.Diagnostics;
+using System.Reflection;
+using System.Threading;
+
+
+namespace Crow
+{
+       public class Group : Widget
+    {
+               #if DESIGN_MODE
+               public override bool FindByDesignID(string designID, out Widget go){
+                       go = null;
+                       if (base.FindByDesignID (designID, out go))
+                               return true;
+                       childrenRWLock.EnterReadLock ();
+                       foreach (Widget w in Children) {
+                               if (!w.FindByDesignID (designID, out go))
+                                       continue;
+                               childrenRWLock.ExitReadLock ();
+                               return true;
+                       }
+                       childrenRWLock.ExitReadLock ();
+                       return false;
+               }
+               public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem)
+               {
+                       if (this.design_isTGItem)
+                               return;
+                       base.getIML (doc, parentElem);
+                       foreach (Widget g in Children) {
+                               g.getIML (doc, parentElem.LastChild);   
+                       }
+               }
+               #endif
+
+               protected ReaderWriterLockSlim childrenRWLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
+
+               #region CTOR
+               public Group () : base() {}
+               public Group(Interface iface) : base(iface){}
+               #endregion
+
+               #region EVENT HANDLERS
+               public event EventHandler<EventArgs> ChildrenCleared;
+               #endregion
+
+               internal Widget largestChild = null;
+               internal Widget tallestChild = null;
+
+        bool _multiSelect = false;
+               List<Widget> children = new List<Widget>();
+
+        public virtual List<Widget> Children {
+                       get { return children; }
+               }
+               [DefaultValue(false)]
+        public bool MultiSelect
+        {
+            get { return _multiSelect; }
+            set { _multiSelect = value; }
+        }
+               public virtual void AddChild(Widget g){
+                       childrenRWLock.EnterWriteLock();
+
+                       g.Parent = this;
+                       Children.Add (g);
+
+                       childrenRWLock.ExitWriteLock();
+
+                       g.RegisteredLayoutings = LayoutingType.None;
+                       g.LayoutChanged += OnChildLayoutChanges;
+                       g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
+               }
+        public virtual void RemoveChild(Widget child)
+               {
+                       child.LayoutChanged -= OnChildLayoutChanges;
+                       //check if HoverWidget is removed from Tree
+                       if (IFace.HoverWidget != null) {
+                               if (this.Contains (IFace.HoverWidget))
+                                       IFace.HoverWidget = null;
+                       }
+
+                       childrenRWLock.EnterWriteLock ();
+
+                       Children.Remove(child);
+                       child.Parent = null;
+
+                       childrenRWLock.ExitWriteLock ();
+
+                       if (child == largestChild && Width == Measure.Fit)
+                               searchLargestChild ();
+                       if (child == tallestChild && Height == Measure.Fit)
+                               searchTallestChild ();
+
+                       this.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
+
+               }
+        public virtual void DeleteChild(Widget child)
+               {
+                       RemoveChild (child);
+                       child.Dispose ();
+        }
+               public virtual void InsertChild (int idx, Widget g) {
+                       childrenRWLock.EnterWriteLock ();
+                               
+                       g.Parent = this;
+                       Children.Insert (idx, g);
+
+                       childrenRWLock.ExitWriteLock ();
+
+                       g.RegisteredLayoutings = LayoutingType.None;
+                       g.LayoutChanged += OnChildLayoutChanges;
+                       g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
+               }
+               public virtual void RemoveChild (int idx) {
+                       RemoveChild (children[idx]);
+               }
+               public virtual void DeleteChild (int idx) {
+                       DeleteChild (children[idx]);
+               }
+               public virtual void ClearChildren()
+               {
+                       childrenRWLock.EnterWriteLock ();
+
+                       while (Children.Count > 0) {
+                               Widget g = Children [Children.Count - 1];
+                               g.LayoutChanged -= OnChildLayoutChanges;
+                               Children.RemoveAt (Children.Count - 1);
+                               g.Dispose ();
+                       }
+
+                       childrenRWLock.ExitWriteLock ();
+
+                       resetChildrenMaxSize ();
+
+                       this.RegisterForLayouting (LayoutingType.Sizing);
+                       ChildrenCleared.Raise (this, new EventArgs ());
+               }
+               public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
+               {
+                       base.OnDataSourceChanged (this, e);
+
+                       childrenRWLock.EnterReadLock ();
+                       foreach (Widget g in Children) {
+                               if (g.localDataSourceIsNull & g.localLogicalParentIsNull)
+                                       g.OnDataSourceChanged (g, e);   
+                       }
+                       childrenRWLock.ExitReadLock ();
+               }
+
+               public void putWidgetOnTop(Widget w)
+               {
+                       if (Children.Contains(w))
+                       {
+                               childrenRWLock.EnterWriteLock ();
+
+                               Children.Remove (w);
+                               Children.Add (w);
+
+                               childrenRWLock.ExitWriteLock ();
+                       }
+               }
+               public void putWidgetOnBottom(Widget w)
+               {
+                       if (Children.Contains(w))
+                       {
+                               childrenRWLock.EnterWriteLock ();
+
+                               Children.Remove (w);
+                               Children.Insert (0, w);
+
+                               childrenRWLock.ExitWriteLock ();
+                       }
+               }
+
+               #region GraphicObject overrides
+
+               public override Widget FindByName (string nameToFind)
+               {
+                       if (Name == nameToFind)
+                               return this;
+                       Widget tmp = null;
+
+                       childrenRWLock.EnterReadLock ();
+
+                       foreach (Widget w in Children) {
+                               tmp = w.FindByName (nameToFind);
+                               if (tmp != null)
+                                       break;
+                       }
+
+                       childrenRWLock.ExitReadLock ();
+
+                       return tmp;
+               }
+               public override bool Contains (Widget goToFind)
+               {
+                       foreach (Widget w in Children) {
+                               if (w == goToFind)
+                                       return true;
+                               if (w.Contains (goToFind))
+                                       return true;
+                       }
+                       return false;
+               }
+               protected override int measureRawSize (LayoutingType lt)
+               {
+                       if (Children.Count > 0) {
+                               if (lt == LayoutingType.Width) {
+                                       if (largestChild == null)
+                                               searchLargestChild ();
+                                       if (largestChild == null) {
+                                               //if still null, not possible to determine a width
+                                               //because all children are stretched, force first one to fit
+                                               Children [0].Width = Measure.Fit;
+                                               return -1;//cancel actual sizing to let child computation take place
+                                       }
+                               } else {
+                                       if (tallestChild == null)
+                                               searchTallestChild ();
+                                       if (tallestChild == null) {
+                                               Children [0].Height = Measure.Fit;
+                                               return -1;
+                                       }
+                               }
+                       }
+                       return base.measureRawSize (lt);
+               }
+
+               public override void OnLayoutChanges (LayoutingType layoutType)
+               {
+                       base.OnLayoutChanges (layoutType);
+
+                       childrenRWLock.EnterReadLock ();
+                       //position smaller objects in group when group size is fit
+                       switch (layoutType) {
+                       case LayoutingType.Width:
+                               foreach (Widget c in Children) {
+                                       if (c.Width.IsRelativeToParent)
+                                               c.RegisterForLayouting (LayoutingType.Width);
+                                       else
+                                               c.RegisterForLayouting (LayoutingType.X);
+                               }
+                               break;
+                       case LayoutingType.Height:
+                               foreach (Widget c in Children) {
+                                       if (c.Height.IsRelativeToParent)
+                                               c.RegisterForLayouting (LayoutingType.Height);
+                                       else
+                                               c.RegisterForLayouting (LayoutingType.Y);
+                               }
+                               break;
+                       }
+                       childrenRWLock.ExitReadLock ();
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       gr.Save ();
+
+                       if (ClipToClientRect) {
+                               //clip to client zone
+                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
+                               gr.Clip ();
+                       }
+
+                       childrenRWLock.EnterReadLock ();
+
+                       for (int i = 0; i < Children.Count; i++) 
+                               Children[i].Paint (ref gr);                     
+
+                       childrenRWLock.ExitReadLock ();
+                       gr.Restore ();
+               }
+               protected override void UpdateCache (Context ctx)
+               {
+                       Rectangle rb = Slot + Parent.ClientRectangle.Position;
+
+
+                       Context gr = new Context (bmp);
+
+                       if (!Clipping.IsEmpty) {
+                               for (int i = 0; i < Clipping.NumRectangles; i++)
+                                       gr.Rectangle(Clipping.GetRectangle(i));
+                               gr.ClipPreserve();
+                               gr.Operator = Operator.Clear;
+                               gr.Fill();
+                               gr.Operator = Operator.Over;
+
+                               base.onDraw (gr);
+
+                               if (ClipToClientRect) {
+                                       CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
+                                       gr.Clip ();
+                               }
+
+                               childrenRWLock.EnterReadLock ();
+
+                               foreach (Widget c in Children) {
+                                       if (!c.Visible)
+                                               continue;
+                                       if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out)
+                                               continue;
+                                       c.Paint (ref gr);
+                               }
+
+                               childrenRWLock.ExitReadLock ();
+
+                               #if DEBUG_CLIP_RECTANGLE
+                               /*gr.LineWidth = 1;
+                               gr.SetSourceColor(Color.DarkMagenta.AdjustAlpha (0.8));
+                               for (int i = 0; i < Clipping.NumRectangles; i++)
+                                       gr.Rectangle(Clipping.GetRectangle(i));
+                               gr.Stroke ();*/
+                               #endif
+                       }
+                       gr.Dispose ();
+
+                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
+                       ctx.Paint ();
+
+                       Clipping.Dispose();
+                       Clipping = new Region ();
+               }
+               #endregion
+
+               public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
+               {
+                       Widget g = sender as Widget;
+
+                       switch (arg.LayoutType) {
+                       case LayoutingType.Width:
+                               if (Width != Measure.Fit)
+                                       return;
+                               if (g.Slot.Width > contentSize.Width) {
+                                       largestChild = g;
+                                       contentSize.Width = g.Slot.Width;
+                               } else if (g == largestChild)
+                                       searchLargestChild ();
+
+                               this.RegisterForLayouting (LayoutingType.Width);
+                               break;
+                       case LayoutingType.Height:
+                               if (Height != Measure.Fit)
+                                       return;
+                               if (g.Slot.Height > contentSize.Height) {
+                                       tallestChild = g;
+                                       contentSize.Height = g.Slot.Height;
+                               } else if (g == tallestChild)
+                                       searchTallestChild ();
+
+                               this.RegisterForLayouting (LayoutingType.Height);
+                               break;
+                       }
+               }
+               //TODO: x,y position should be taken in account for computation of width and height
+               void resetChildrenMaxSize(){
+                       largestChild = null;
+                       tallestChild = null;
+                       contentSize = 0;
+               }
+               void searchLargestChild(){
+                       #if DEBUG_LAYOUTING
+                       Debug.WriteLine("\tSearch largest child");
+                       #endif
+                       largestChild = null;
+                       contentSize.Width = 0;
+                       for (int i = 0; i < Children.Count; i++) {
+                               if (!Children [i].Visible)
+                                       continue;
+                               if (children [i].RegisteredLayoutings.HasFlag (LayoutingType.Width))
+                                       continue;
+                               if (Children [i].Slot.Width > contentSize.Width) {
+                                       contentSize.Width = Children [i].Slot.Width;
+                                       largestChild = Children [i];
+                               }
+                       }
+               }
+               void searchTallestChild(){
+                       #if DEBUG_LAYOUTING
+                       Debug.WriteLine("\tSearch tallest child");
+                       #endif
+                       tallestChild = null;
+                       contentSize.Height = 0;
+                       for (int i = 0; i < Children.Count; i++) {
+                               if (!Children [i].Visible)
+                                       continue;
+                               if (children [i].RegisteredLayoutings.HasFlag (LayoutingType.Height))
+                                       continue;
+                               if (Children [i].Slot.Height > contentSize.Height) {
+                                       contentSize.Height = Children [i].Slot.Height;
+                                       tallestChild = Children [i];
+                               }
+                       }
+               }
+
+
+               #region Mouse handling
+               public override void checkHoverWidget (MouseMoveEventArgs e)
+               {
+                       if (IFace.HoverWidget != this) {
+                               IFace.HoverWidget = this;
+                               onMouseEnter (this, e);
+                       }
+                       for (int i = Children.Count - 1; i >= 0; i--) {
+                               if (Children[i].MouseIsIn(e.Position))
+                               {
+                                       Children[i].checkHoverWidget (e);
+                                       return;
+                               }
+                       }
+                       base.checkHoverWidget (e);
+               }
+//             public override bool PointIsIn (ref Point m)
+//             {
+//                     if (!base.PointIsIn (ref m))
+//                             return false;
+//                     if (CurrentInterface.HoverWidget == this)
+//                             return true;
+//                     lock (Children) {
+//                             for (int i = Children.Count - 1; i >= 0; i--) {
+//                                     if (Children [i].Slot.ContainsOrIsEqual (m) && !(bool)CurrentInterface.HoverWidget?.IsOrIsInside(Children[i])) {                                                
+//                                             return false;
+//                                     }
+//                             }
+//                     }
+//                     return true;
+//             }
+               #endregion
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (disposing) {
+                               foreach (Widget c in children)
+                                       c.Dispose ();
+                       }
+                       base.Dispose (disposing);
+               }
+       }
+}
diff --git a/Crow/src/Widgets/GroupBox.cs b/Crow/src/Widgets/GroupBox.cs
new file mode 100644 (file)
index 0000000..2e32ddd
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// GroupBox.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated container accepting one child
+       /// </summary>
+    public class GroupBox : TemplatedContainer
+    {          
+               #region CTOR
+               protected GroupBox () : base(){}
+               public GroupBox(Interface iface) : base(iface){}
+               #endregion
+       }
+}
diff --git a/Crow/src/Widgets/HorizontalStack.cs b/Crow/src/Widgets/HorizontalStack.cs
new file mode 100644 (file)
index 0000000..64d7cae
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// HorizontalStack.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.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace Crow
+{
+       /// <summary>
+       /// group control stacking its children horizontally
+       /// </summary>
+    public class HorizontalStack : GenericStack
+    {
+               #region CTOR
+               protected HorizontalStack () : base(){}
+               public HorizontalStack(Interface iface) : base(iface)
+        {            
+        }
+               #endregion
+
+        [XmlIgnore]
+        public override Orientation Orientation
+        {
+            get { return Orientation.Horizontal; }
+        }
+    }
+}
diff --git a/Crow/src/Widgets/HueSelector.cs b/Crow/src/Widgets/HueSelector.cs
new file mode 100644 (file)
index 0000000..eb00a04
--- /dev/null
@@ -0,0 +1,174 @@
+//
+// HueSelector.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.Xml.Serialization;
+using System.ComponentModel;
+using Crow.Cairo;
+
+namespace Crow
+{
+       [DesignIgnore]
+       public class HueSelector : ColorSelector
+       {
+               #region CTOR
+               protected HueSelector () : base(){}
+               public HueSelector (Interface iface) : base(iface)
+               {
+               }
+               #endregion
+
+               Orientation _orientation;
+               double hue;
+               CursorType cursor = CursorType.Pentagone;
+
+               [DefaultValue(Orientation.Horizontal)]
+               public virtual Orientation Orientation
+               {
+                       get { return _orientation; }
+                       set {
+                               if (_orientation == value)
+                                       return;
+                               _orientation = value;
+                               NotifyValueChanged ("Orientation", _orientation);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               
+               public virtual double Hue {
+                       get { return hue; }
+                       set {
+                               if (hue == value)
+                                       return;
+                               hue = value;
+                               notifyHueChanged ();
+                               updateMousePosFromHue ();
+                               RegisterForRedraw ();
+                       }
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       RectangleD r = ClientRectangle;
+                       r.Height -= 4;
+                       r.Y += 2;
+
+                       Gradient.Type gt = Gradient.Type.Horizontal;
+                       if (Orientation == Orientation.Vertical)
+                               gt = Gradient.Type.Vertical;
+
+                       Gradient grad = new Gradient (gt);
+
+                       grad.Stops.Add (new Gradient.ColorStop (0,     new Color (1, 0, 0, 1)));
+                       grad.Stops.Add (new Gradient.ColorStop (0.167, new Color (1, 1, 0, 1)));
+                       grad.Stops.Add (new Gradient.ColorStop (0.333, new Color (0, 1, 0, 1)));
+                       grad.Stops.Add (new Gradient.ColorStop (0.5,   new Color (0, 1, 1, 1)));
+                       grad.Stops.Add (new Gradient.ColorStop (0.667, new Color (0, 0, 1, 1)));
+                       grad.Stops.Add (new Gradient.ColorStop (0.833, new Color (1, 0, 1, 1)));
+                       grad.Stops.Add (new Gradient.ColorStop (1,     new Color (1, 0, 0, 1)));
+
+                       grad.SetAsSource (gr, r);
+                       CairoHelpers.CairoRectangle (gr, r, CornerRadius);
+                       gr.Fill();
+
+                       r = ClientRectangle;
+
+                       switch (cursor) {
+                       case CursorType.Rectangle:
+                               if (Orientation == Orientation.Horizontal) {
+                                       r.Width = 5;
+                                       r.X = mousePos.X - 2.5;
+                               } else {
+                                       r.Height = 5;
+                                       r.Y = mousePos.Y - 2.5;
+                               }
+                               CairoHelpers.CairoRectangle (gr, r, 1);
+                               break;
+                       case CursorType.Circle:
+                               if (Orientation == Orientation.Horizontal)
+                                       gr.Arc (mousePos.X, r.Center.Y, 3.5, 0, Math.PI * 2.0);
+                               else
+                                       gr.Arc (r.Center.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
+                               break;
+                       case CursorType.Pentagone:
+                               if (Orientation == Orientation.Horizontal) {
+                                       r.Width = 5;
+                                       r.X = mousePos.X - 2.5;
+                                       double y = r.CenterD.Y-r.Height*0.2;
+                                       gr.MoveTo (mousePos.X, y);
+                                       y += r.Height * 0.15;
+                                       gr.LineTo (r.Right, y);
+                                       gr.LineTo (r.Right, r.Bottom-0.5);
+                                       gr.LineTo (r.Left, r.Bottom-0.5);
+                                       gr.LineTo (r.Left, y);
+                                       gr.ClosePath ();
+                               } else { 
+                               }
+                               break;                  
+                       }
+
+                       gr.SetSourceColor (Color.Black);
+                       gr.LineWidth = 2.0;
+                       gr.StrokePreserve ();
+                       gr.SetSourceColor (Color.White);
+                       gr.LineWidth = 1.0;
+                       gr.Stroke ();
+               }
+
+               public override void OnLayoutChanges (LayoutingType layoutType)
+               {
+                       base.OnLayoutChanges (layoutType);
+
+                       if (Orientation == Orientation.Horizontal) {
+                               if (layoutType == LayoutingType.Width)
+                                       updateMousePosFromHue ();
+                       } else if (layoutType == LayoutingType.Height)
+                               updateMousePosFromHue ();
+               }
+               protected override void updateMouseLocalPos (Point mPos)
+               {
+                       base.updateMouseLocalPos (mPos);
+                       if (Orientation == Orientation.Horizontal)
+                               hue = (double)mousePos.X / (double)ClientRectangle.Width;
+                       else
+                               hue = (double)mousePos.Y / (double)ClientRectangle.Height;
+                       notifyHueChanged ();
+                       RegisterForRedraw ();
+               }
+               void updateMousePosFromHue(){
+                       if (Orientation == Orientation.Horizontal)
+                               mousePos.X = (int)Math.Floor(hue * (double)ClientRectangle.Width);
+                       else
+                               mousePos.Y = (int)Math.Floor(hue * (double)ClientRectangle.Height);
+               }
+               void notifyHueChanged(){
+                       NotifyValueChanged ("Hue", hue);
+                       NotifyValueChanged ("HueColor", new SolidColor (Color.FromHSV (hue)));
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/ILayoutable.cs b/Crow/src/Widgets/ILayoutable.cs
new file mode 100644 (file)
index 0000000..c8aa38f
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// ILayoutable.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.Collections.Generic;
+
+namespace Crow
+{
+       public interface ILayoutable
+       {
+               /// <summary> Parent in the graphic tree </summary>
+               ILayoutable Parent { get; set; }
+               /// <summary> The logical parent (used mainly for bindings) as opposed
+               ///  to the parent in the graphic tree </summary>
+               ILayoutable LogicalParent { get; set; }
+
+               Rectangle ClientRectangle { get; }
+               Rectangle getSlot();
+
+               bool ArrangeChildren { get; }
+               LayoutingType RegisteredLayoutings { get; set; }
+               void RegisterForLayouting(LayoutingType layoutType);
+               void RegisterClip(Rectangle clip);
+               bool UpdateLayout(LayoutingType layoutType);
+               bool PointIsIn(ref Point m);
+
+               Rectangle ContextCoordinates(Rectangle r);
+               Rectangle ScreenCoordinates (Rectangle r);
+
+       }
+}
+
diff --git a/Crow/src/Widgets/IMLContainer.cs b/Crow/src/Widgets/IMLContainer.cs
new file mode 100644 (file)
index 0000000..8ba161a
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// IMLContainer.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;
+
+namespace Crow
+{
+       public class IMLContainer : PrivateContainer
+       {
+               public IMLContainer () : base()
+               {
+               }
+
+               string path;
+
+               public string Path {
+                       get { return path; }
+                       set {
+                               if (path == value)
+                                       return;
+                               path = value;
+                               this.SetChild (IFace.CreateInstance (path));
+                               NotifyValueChanged ("Path", path);
+                       }
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/IValueChange.cs b/Crow/src/Widgets/IValueChange.cs
new file mode 100644 (file)
index 0000000..7e18e5e
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// IValueChange.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;
+
+namespace Crow
+{
+       public interface IValueChange
+       {
+               event EventHandler<ValueChangeEventArgs> ValueChanged;
+       }
+}
+
diff --git a/Crow/src/Widgets/Image.cs b/Crow/src/Widgets/Image.cs
new file mode 100644 (file)
index 0000000..98f86e5
--- /dev/null
@@ -0,0 +1,215 @@
+//
+// Image.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 Crow.Cairo;
+using System.Xml.Serialization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+
+namespace Crow
+{
+       /// <summary>
+       /// Base widget to display an image. Accepts bitmaps and SVGs.
+       /// </summary>
+       /// <remarks>
+       /// </remarks>
+       public class Image : Widget
+       {
+               Picture _pic;
+               string _svgSub;
+               bool scaled, keepProps;
+               double opacity;
+
+               #region Public properties
+               /// <summary>
+               /// If false, original size will be kept in any case.
+               /// </summary>
+               [DefaultValue(true)]
+               public virtual bool Scaled {
+                       get { return scaled; }
+                       set {
+                               if (scaled == value)
+                                       return;
+                               scaled = value;
+                               NotifyValueChanged ("Scaled", scaled);
+                               if (_pic == null)
+                                       return;
+                               _pic.Scaled = scaled;
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary>
+               /// If image is scaled, proportions will be preserved.
+               /// </summary>
+               [DefaultValue(true)]
+               public virtual bool KeepProportions {
+                       get { return keepProps; }
+                       set {
+                               if (keepProps == value)
+                                       return;
+                               keepProps = value;
+                               NotifyValueChanged ("KeepProportions", keepProps);
+                               if (_pic == null)
+                                       return;
+                               _pic.KeepProportions = keepProps;
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary>
+               /// Image file path, may be on disk or embedded. Accepts bitmaps or SVG drawings.
+               /// </summary>
+        
+               public string Path {
+                       get { return _pic == null ? "" : _pic.Path; }
+                       set {
+                               if (value == Path)
+                                       return;
+                               try {
+                                       if (string.IsNullOrEmpty(value))
+                                               Picture = null;
+                                       else {
+                                               //lock(IFace.LayoutMutex){
+                                                       LoadImage (value);
+                                               //}
+                                       }
+                               } catch (Exception ex) {
+                                       Debug.WriteLine (ex.Message);
+                                       _pic = null;
+                               }
+                               NotifyValueChanged ("Path", Path);
+                       }
+               }
+               /// <summary>
+               /// Used only for svg images, repaint only node named referenced in SvgSub.
+               /// If null, all the svg is rendered
+               /// </summary>
+               
+               public string SvgSub {
+                       get { return _svgSub; }
+                       set {
+                               if (_svgSub == value)
+                                       return;
+                               _svgSub = value;
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary>
+               /// Object holding the image data once loaded, may be used directely to pupulate this control without 
+               /// specifying a path.
+               /// </summary>
+               
+               public Picture Picture {
+                       get { return _pic; }
+                       set {
+                               if (_pic == value)
+                                       return;
+                               _pic = value;
+                               NotifyValueChanged ("Picture", _pic);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary>
+               /// Opacity parameter for the image
+               /// </summary>
+               // TODO:could be moved in GraphicObject
+               [DefaultValue(1.0)]
+               public virtual double Opacity {
+                       get { return opacity; }
+                       set {
+                               if (opacity == value)
+                                       return;
+                               opacity = value;
+                               NotifyValueChanged ("Faded", opacity);
+                               RegisterForRedraw ();
+                       }
+               }
+               #endregion
+
+               #region CTOR
+               /// <summary>
+               /// Initializes a new instance of the <see cref="Crow.Image"/> class.
+               /// </summary>
+               protected Image () : base(){}
+               /// <summary>
+               /// Initializes a new instance of the <see cref="Crow.Image"/> class from code
+               /// </summary>
+               /// <param name="iface">interface to bound to</param>
+               public Image (Interface iface) : base(iface)
+               {
+               }
+               #endregion
+
+               #region Image Loading
+               public void LoadImage (string path)
+               {
+                       Picture pic;
+                       if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture))
+                               pic = new SvgPicture (path);
+                       else
+                               pic = new BmpPicture (path);
+
+
+                       pic.Scaled = scaled;
+                       pic.KeepProportions = keepProps;
+
+                       Picture = pic;
+               }
+               #endregion
+
+               #region GraphicObject overrides
+               protected override int measureRawSize (LayoutingType lt)
+               {
+                       if (_pic == null)
+                               return 2 * Margin;
+                               //_pic = "#Crow.Images.Icons.IconAlerte.svg";
+                       //TODO:take scalling in account
+                       if (lt == LayoutingType.Width)
+                               return _pic.Dimensions.Width + 2 * Margin;
+                       else
+                               return _pic.Dimensions.Height + 2 * Margin;
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       if (_pic == null)
+                               return;
+
+                       _pic.Paint (gr, ClientRectangle, _svgSub);
+
+                       if (Opacity<1.0) {
+                               gr.SetSourceRGBA (0.0, 0.0, 0.0, 1.0-Opacity);
+                               gr.Operator = Operator.DestOut;
+                               gr.Rectangle (ClientRectangle);
+                               gr.Fill ();
+                               gr.Operator = Operator.Over;
+                       }
+               }
+               #endregion
+       }
+}
diff --git a/Crow/src/Widgets/Label.cs b/Crow/src/Widgets/Label.cs
new file mode 100644 (file)
index 0000000..f597f5d
--- /dev/null
@@ -0,0 +1,833 @@
+//
+// Label.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.Collections.Generic;
+using System.Linq;
+using System.Diagnostics;
+using Crow.Cairo;
+using System.Text.RegularExpressions;
+using System.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+    public class Label : Widget
+    {
+               #region CTOR
+               protected Label () : base(){}
+
+               public Label(Interface iface) : base(iface)
+               {
+
+               }
+//             public Label(string _text)
+//                     : base()
+//             {
+//                     Text = _text;
+//             }
+               #endregion
+
+               public event EventHandler<TextChangeEventArgs> TextChanged;
+
+               public virtual void OnTextChanged(Object sender, TextChangeEventArgs e)
+               {
+                       textMeasureIsUpToDate = false;
+                       NotifyValueChanged ("Text", Text);
+                       TextChanged.Raise (this, e);
+               }
+        //TODO:change protected to private
+
+               #region private and protected fields
+               string _text = "label";
+        Alignment _textAlignment;
+               bool horizontalStretch;
+               bool verticalStretch;
+               bool _selectable;
+               bool _multiline;
+               Color selBackground;
+               Color selForeground;
+               Point mouseLocalPos = -1;//mouse coord in widget space, filled only when clicked
+               int _currentCol;        //0 based cursor position in string
+               int _currentLine;
+               Point _selBegin = -1;   //selection start (row,column)
+               Point _selRelease = -1; //selection end (row,column)
+               double textCursorPos;   //cursor position in cairo units in widget client coord.
+               double SelStartCursorPos = -1;
+               double SelEndCursorPos = -1;
+               bool SelectionInProgress = false;
+
+        protected Rectangle rText;
+               protected float widthRatio = 1f;
+               protected float heightRatio = 1f;
+               protected FontExtents fe;
+               protected TextExtents te;
+               #endregion
+
+               [DefaultValue("SteelBlue")]
+               public virtual Color SelectionBackground {
+                       get { return selBackground; }
+                       set {
+                               if (value == selBackground)
+                                       return;
+                               selBackground = value;
+                               NotifyValueChanged ("SelectionBackground", selBackground);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue("White")]
+               public virtual Color SelectionForeground {
+                       get { return selForeground; }
+                       set {
+                               if (value == selForeground)
+                                       return;
+                               selForeground = value;
+                               NotifyValueChanged ("SelectionForeground", selForeground);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(Alignment.Left)]
+               public Alignment TextAlignment
+        {
+            get { return _textAlignment; }
+            set {
+                               if (value == _textAlignment)
+                                       return;
+                               _textAlignment = value;
+                               RegisterForRedraw ();
+                               NotifyValueChanged ("TextAlignment", _textAlignment);
+                       }
+        }
+               [DefaultValue(false)]
+               public virtual bool HorizontalStretch {
+                       get { return horizontalStretch; }
+                       set {
+                               if (horizontalStretch == value)
+                                       return;
+                               horizontalStretch = value;
+                               RegisterForRedraw ();
+                               NotifyValueChanged ("HorizontalStretch", horizontalStretch);
+                       }
+               }
+               [DefaultValue(false)]
+               public virtual bool VerticalStretch {
+                       get { return verticalStretch; }
+                       set {
+                               if (verticalStretch == value)
+                                       return;
+                               verticalStretch = value;
+                               RegisterForRedraw ();
+                               NotifyValueChanged ("VerticalStretch", verticalStretch);
+                       }
+               }
+               [DefaultValue("label")]
+        public string Text
+        {
+            get {
+                               return lines == null ?
+                                       _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j);
+                       }
+            set
+            {
+                               if (string.Equals (value, _text, StringComparison.Ordinal))
+                    return;
+
+                _text = value;
+
+                               if (string.IsNullOrEmpty(_text))
+                                       _text = "";
+
+                               lines = getLines;
+
+                               OnTextChanged (this, new TextChangeEventArgs (Text));
+                               RegisterForGraphicUpdate ();
+            }
+        }
+               [DefaultValue(false)]
+               public bool Selectable
+               {
+                       get { return _selectable; }
+                       set
+                       {
+                               if (value == _selectable)
+                                       return;
+                               _selectable = value;
+                               NotifyValueChanged ("Selectable", _selectable);
+                               SelBegin = -1;
+                               SelRelease = -1;
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(false)]
+               public bool Multiline
+               {
+                       get { return _multiline; }
+                       set
+                       {
+                               if (value == _multiline)
+                                       return;
+                               _multiline = value;
+                               NotifyValueChanged ("Multiline", _multiline);
+                               RegisterForGraphicUpdate();
+                       }
+               }
+               [DefaultValue(0)]
+               public int CurrentColumn{
+                       get { return _currentCol; }
+                       set {
+                               if (value == _currentCol)
+                                       return;
+                               if (value < 0)
+                                       _currentCol = 0;
+                               else if (value > lines [_currentLine].Length)
+                                       _currentCol = lines [_currentLine].Length;
+                               else
+                                       _currentCol = value;
+                               NotifyValueChanged ("CurrentColumn", _currentCol);
+                       }
+               }
+               [DefaultValue(0)]
+               public int CurrentLine{
+                       get { return _currentLine; }
+                       set {
+                               if (value == _currentLine)
+                                       return;
+                               if (value >= lines.Count)
+                                       _currentLine = lines.Count-1;
+                               else if (value < 0)
+                                       _currentLine = 0;
+                               else
+                                       _currentLine = value;
+                               //force recheck of currentCol for bounding
+                               int cc = _currentCol;
+                               _currentCol = 0;
+                               CurrentColumn = cc;
+                               NotifyValueChanged ("CurrentLine", _currentLine);
+                       }
+               }
+               [XmlIgnore]public Point CurrentPosition {
+                       get { return new Point(_currentCol, CurrentLine); }
+               }
+               //TODO:using HasFocus for drawing selection cause SelBegin and Release binding not to work
+               /// <summary>
+               /// Selection begin position in char units
+               /// </summary>
+               [DefaultValue("-1")]
+               public Point SelBegin {
+                       get {
+                               return _selBegin;
+                       }
+                       set {
+                               if (value == _selBegin)
+                                       return;
+                               _selBegin = value;
+                               NotifyValueChanged ("SelBegin", _selBegin);
+                               NotifyValueChanged ("SelectedText", SelectedText);
+                       }
+               }
+               [DefaultValue("-1")]
+               public Point SelRelease {
+                       get {
+                               return _selRelease;
+                       }
+                       set {
+                               if (value == _selRelease)
+                                       return;
+                               _selRelease = value;
+                               NotifyValueChanged ("SelRelease", _selRelease);
+                               NotifyValueChanged ("SelectedText", SelectedText);
+                       }
+               }
+               /// <summary>
+               /// return char at CurrentLine, CurrentColumn
+               /// </summary>
+               [XmlIgnore]protected Char CurrentChar
+               {
+                       get {
+                               return lines [CurrentLine] [CurrentColumn];
+                       }
+               }
+               /// <summary>
+               /// ordered selection start and end positions in char units
+               /// </summary>
+               [XmlIgnore]protected Point selectionStart
+               {
+                       get {
+                               return SelRelease < 0 || SelBegin.Y < SelRelease.Y ? SelBegin :
+                                       SelBegin.Y > SelRelease.Y ? SelRelease :
+                                       SelBegin.X < SelRelease.X ? SelBegin : SelRelease;
+                       }
+               }
+               [XmlIgnore]public Point selectionEnd
+               {
+                       get {
+                               return SelRelease < 0 || SelBegin.Y > SelRelease.Y ? SelBegin :
+                                       SelBegin.Y < SelRelease.Y ? SelRelease :
+                                       SelBegin.X > SelRelease.X ? SelBegin : SelRelease;
+                       }
+               }
+               [XmlIgnore]public string SelectedText
+               {
+                       get {
+
+                               if (SelRelease < 0 || SelBegin < 0)
+                                       return "";
+                               if (selectionStart.Y == selectionEnd.Y)
+                                       return lines [selectionStart.Y].Substring (selectionStart.X, selectionEnd.X - selectionStart.X);
+                               string tmp = "";
+                               tmp = lines [selectionStart.Y].Substring (selectionStart.X);
+                               for (int l = selectionStart.Y + 1; l < selectionEnd.Y; l++) {
+                                       tmp += Interface.LineBreak + lines [l];
+                               }
+                               tmp += Interface.LineBreak + lines [selectionEnd.Y].Substring (0, selectionEnd.X);
+                               return tmp;
+                       }
+               }
+               [XmlIgnore]public bool selectionIsEmpty
+               { get { return SelRelease < 0; } }
+
+               List<string> lines;
+               List<string> getLines {
+                       get {
+                               return _multiline ?
+                                       Regex.Split (_text, "\r\n|\r|\n|\\\\n").ToList() :
+                                       new List<string>(new string[] { _text });
+                       }
+               }
+               /// <summary>
+               /// Moves cursor one char to the left.
+               /// </summary>
+               /// <returns><c>true</c> if move succeed</returns>
+               public bool MoveLeft(){
+                       int tmp = _currentCol - 1;
+                       if (tmp < 0) {
+                               if (_currentLine == 0)
+                                       return false;
+                               CurrentLine--;
+                               CurrentColumn = int.MaxValue;
+                       } else
+                               CurrentColumn = tmp;
+                       return true;
+               }
+               /// <summary>
+               /// Moves cursor one char to the right.
+               /// </summary>
+               /// <returns><c>true</c> if move succeed</returns>
+               public bool MoveRight(){
+                       int tmp = _currentCol + 1;
+                       if (tmp > lines [_currentLine].Length){
+                               if (CurrentLine == lines.Count - 1)
+                                       return false;
+                               CurrentLine++;
+                               CurrentColumn = 0;
+                       } else
+                               CurrentColumn = tmp;
+                       return true;
+               }
+               public void GotoWordStart(){
+                       CurrentColumn--;
+                       //skip white spaces
+                       while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0)
+                               CurrentColumn--;
+                       while (char.IsLetterOrDigit (lines [CurrentLine] [CurrentColumn]) && CurrentColumn > 0)
+                               CurrentColumn--;
+                       if (!char.IsLetterOrDigit (this.CurrentChar))
+                               CurrentColumn++;
+               }
+               public void GotoWordEnd(){
+                       //skip white spaces
+                       if (CurrentColumn >= lines [CurrentLine].Length - 1)
+                               return;
+                       while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < lines [CurrentLine].Length-1)
+                               CurrentColumn++;
+                       while (char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < lines [CurrentLine].Length-1)
+                               CurrentColumn++;
+                       if (char.IsLetterOrDigit (this.CurrentChar))
+                               CurrentColumn++;
+               }
+               public void DeleteChar()
+               {
+                       if (selectionIsEmpty) {
+                               if (CurrentColumn == 0) {
+                                       if (CurrentLine == 0 && lines.Count == 1)
+                                               return;
+                                       CurrentLine--;
+                                       CurrentColumn = lines [CurrentLine].Length;
+                                       lines [CurrentLine] += lines [CurrentLine + 1];
+                                       lines.RemoveAt (CurrentLine + 1);
+
+                                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                                       return;
+                               }
+                               CurrentColumn--;
+                               lines [CurrentLine] = lines [CurrentLine].Remove (CurrentColumn, 1);
+                       } else {
+                               int linesToRemove = selectionEnd.Y - selectionStart.Y + 1;
+                               int l = selectionStart.Y;
+
+                               if (linesToRemove > 0) {
+                                       lines [l] = lines [l].Remove (selectionStart.X, lines [l].Length - selectionStart.X) +
+                                               lines [selectionEnd.Y].Substring (selectionEnd.X, lines [selectionEnd.Y].Length - selectionEnd.X);
+                                       l++;
+                                       for (int c = 0; c < linesToRemove-1; c++)
+                                               lines.RemoveAt (l);
+                                       CurrentLine = selectionStart.Y;
+                                       CurrentColumn = selectionStart.X;
+                               } else
+                                       lines [l] = lines [l].Remove (selectionStart.X, selectionEnd.X - selectionStart.X);
+                               CurrentColumn = selectionStart.X;
+                               SelBegin = -1;
+                               SelRelease = -1;
+                       }
+                       OnTextChanged (this, new TextChangeEventArgs (Text));
+               }
+               /// <summary>
+               /// Insert new string at caret position, should be sure no line break is inside.
+               /// </summary>
+               /// <param name="str">String.</param>
+               protected void Insert(string str)
+               {
+                       if (!selectionIsEmpty)
+                               this.DeleteChar ();
+                       if (_multiline) {
+                               string[] strLines = Regex.Split (str, "\r\n|\r|\n|" + @"\\n").ToArray();
+                               lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, strLines[0]);
+                               CurrentColumn += strLines[0].Length;
+                               for (int i = 1; i < strLines.Length; i++) {
+                                       InsertLineBreak ();
+                                       lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, strLines[i]);
+                                       CurrentColumn += strLines[i].Length;
+                               }
+                       } else {
+                               lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, str);
+                               CurrentColumn += str.Length;
+                       }
+                       OnTextChanged (this, new TextChangeEventArgs (Text));
+               }
+               /// <summary>
+               /// Insert a line break.
+               /// </summary>
+               protected void InsertLineBreak()
+               {
+                       lines.Insert(CurrentLine + 1, lines[CurrentLine].Substring(CurrentColumn));
+                       lines [CurrentLine] = lines [CurrentLine].Substring (0, CurrentColumn);
+                       CurrentLine++;
+                       CurrentColumn = 0;
+                       OnTextChanged (this, new TextChangeEventArgs (Text));
+               }
+               bool textMeasureIsUpToDate = false;
+               Size cachedTextSize = default(Size);
+
+               #region GraphicObject overrides
+               protected override int measureRawSize(LayoutingType lt)
+               {
+                       if (lines == null)
+                               lines = getLines;
+                       if (!textMeasureIsUpToDate) {
+                               using (Context gr = new Context (IFace.surf)) {
+                                       //Cairo.FontFace cf = gr.GetContextFontFace ();
+
+                                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+                                       gr.SetFontSize (Font.Size);
+                                       gr.FontOptions = Interface.FontRenderingOptions;
+                                       gr.Antialias = Interface.Antialias;
+
+                                       fe = gr.FontExtents;
+                                       te = new TextExtents ();
+
+                                       cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent+fe.Descent) * Math.Max (1, lines.Count)) + Margin * 2;
+
+                                       try {
+                                               for (int i = 0; i < lines.Count; i++) {
+                                                       string l = lines[i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
+
+                                                       TextExtents tmp = gr.TextExtents (l);
+
+                                                       if (tmp.XAdvance > te.XAdvance)
+                                                               te = tmp;
+                                               }
+                                               cachedTextSize.Width = (int)Math.Ceiling (te.XAdvance) + Margin * 2;
+                                               textMeasureIsUpToDate = true;
+                                       } catch {                                                       
+                                               return -1;
+                                       }                                       
+                               }
+                       }
+                       return lt == LayoutingType.Height ? cachedTextSize.Height : cachedTextSize.Width;
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+                       gr.SetFontSize (Font.Size);
+                       gr.FontOptions = Interface.FontRenderingOptions;
+                       gr.Antialias = Interface.Antialias;
+
+                       rText = new Rectangle(new Size(
+                               measureRawSize(LayoutingType.Width), measureRawSize(LayoutingType.Height)));
+                       rText.Width -= 2 * Margin;
+                       rText.Height -= 2 * Margin;
+
+                       widthRatio = 1f;
+                       heightRatio = 1f;
+
+                       Rectangle cb = ClientRectangle;
+
+                       rText.X = cb.X;
+                       rText.Y = cb.Y;
+
+                       if (horizontalStretch) {
+                               widthRatio = (float)cb.Width / (float)rText.Width;
+                               if (!verticalStretch)
+                                       heightRatio = widthRatio;
+                       }
+
+                       if (verticalStretch) {
+                               heightRatio = (float)cb.Height / (float)rText.Height;
+                               if (!horizontalStretch)
+                                       widthRatio = heightRatio;
+                       }
+
+                       rText.Width = (int)(widthRatio * (float)rText.Width);
+                       rText.Height = (int)(heightRatio * (float)rText.Height);
+
+                       switch (TextAlignment)
+                       {
+                       case Alignment.TopLeft:     //ok
+                               rText.X = cb.X;
+                               rText.Y = cb.Y;
+                               break;
+                       case Alignment.Top:   //ok
+                               rText.Y = cb.Y;
+                               rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
+                               break;
+                       case Alignment.TopRight:    //ok
+                               rText.Y = cb.Y;
+                               rText.X = cb.Right - rText.Width;
+                               break;
+                       case Alignment.Left://ok
+                               rText.X = cb.X;
+                               rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
+                               break;
+                       case Alignment.Right://ok
+                               rText.X = cb.X + cb.Width - rText.Width;
+                               rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
+                               break;
+                       case Alignment.Bottom://ok
+                               rText.X = cb.Width / 2 - rText.Width / 2;
+                               rText.Y = cb.Height - rText.Height;
+                               break;
+                       case Alignment.BottomLeft://ok
+                               rText.X = cb.X;
+                               rText.Y = cb.Bottom - rText.Height;
+                               break;
+                       case Alignment.BottomRight://ok
+                               rText.Y = cb.Bottom - rText.Height;
+                               rText.X = cb.Right - rText.Width;
+                               break;
+                       case Alignment.Center://ok
+                               rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
+                               //rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
+                               rText.Y = cb.Y + (int)Math.Floor((double)cb.Height / 2.0 - (double)rText.Height / 2.0);
+                               break;
+                       }
+
+                       //gr.FontMatrix = new Matrix(widthRatio * (float)Font.Size, 0, 0, heightRatio * (float)Font.Size, 0, 0);
+                       fe = gr.FontExtents;
+
+                       #region draw text cursor
+                       if (HasFocus && Selectable)
+                       {
+                               if (mouseLocalPos >= 0)
+                               {
+                                       computeTextCursor(gr);
+
+                                       if (SelectionInProgress)
+                                       {
+                                               if (SelBegin < 0){
+                                                       SelBegin = new Point(CurrentColumn, CurrentLine);
+                                                       SelStartCursorPos = textCursorPos;
+                                                       SelRelease = -1;
+                                               }else{
+                                                       SelRelease = new Point(CurrentColumn, CurrentLine);
+                                                       if (SelRelease == SelBegin)
+                                                               SelRelease = -1;
+                                                       else
+                                                               SelEndCursorPos = textCursorPos;
+                                               }
+                                       }else
+                                               computeTextCursorPosition(gr);
+                               }else
+                                       computeTextCursorPosition(gr);
+
+                               Foreground.SetAsSource (gr);
+                               gr.LineWidth = 1.0;
+                               gr.MoveTo (0.5 + textCursorPos + rText.X, rText.Y + CurrentLine * (fe.Ascent+fe.Descent));
+                               gr.LineTo (0.5 + textCursorPos + rText.X, rText.Y + (CurrentLine + 1) * (fe.Ascent+fe.Descent));
+                               gr.Stroke();
+                       }
+                       #endregion
+
+                       //****** debug selection *************
+//                     if (SelRelease >= 0) {
+//                             new SolidColor(Color.DarkGreen).SetAsSource(gr);
+//                             Rectangle R = new Rectangle (
+//                                                  rText.X + (int)SelEndCursorPos - 3,
+//                                                  rText.Y + (int)(SelRelease.Y * (fe.Ascent+fe.Descent)),
+//                                                  6,
+//                                                  (int)(fe.Ascent+fe.Descent));
+//                             gr.Rectangle (R);
+//                             gr.Fill ();
+//                     }
+//                     if (SelBegin >= 0) {
+//                             new SolidColor(Color.DarkRed).SetAsSource(gr);
+//                             Rectangle R = new Rectangle (
+//                                     rText.X + (int)SelStartCursorPos - 3,
+//                                     rText.Y + (int)(SelBegin.Y * (fe.Ascent+fe.Descent)),
+//                                     6,
+//                                     (int)(fe.Ascent+fe.Descent));
+//                             gr.Rectangle (R);
+//                             gr.Fill ();
+//                     }
+                       //*******************
+
+                       for (int i = 0; i < lines.Count; i++) {
+                               string l = lines [i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
+                               int lineLength = (int)gr.TextExtents (l).XAdvance;
+                               Rectangle lineRect = new Rectangle (
+                                       rText.X,
+                                       rText.Y + i * (int)(fe.Ascent+fe.Descent),
+                                       lineLength,
+                                       (int)(fe.Ascent+fe.Descent));
+
+//                             if (TextAlignment == Alignment.Center ||
+//                                     TextAlignment == Alignment.Top ||
+//                                     TextAlignment == Alignment.Bottom)
+//                                     lineRect.X += (rText.Width - lineLength) / 2;
+//                             else if (TextAlignment == Alignment.Right ||
+//                                     TextAlignment == Alignment.TopRight ||
+//                                     TextAlignment == Alignment.BottomRight)
+//                                     lineRect.X += (rText.Width - lineLength);
+                               if (string.IsNullOrWhiteSpace (l))
+                                       continue;
+
+                               Foreground.SetAsSource (gr);
+                               gr.MoveTo (lineRect.X,(double)rText.Y + fe.Ascent + (fe.Ascent+fe.Descent) * i) ;
+
+                gr.ShowText (l);
+                               gr.Fill ();
+
+                               if (Selectable) {
+                                       if (SelRelease >= 0 && i >= selectionStart.Y && i <= selectionEnd.Y) {
+                                               gr.SetSourceColor (selBackground);
+
+                                               Rectangle selRect = lineRect;
+
+                                               int cpStart = (int)SelStartCursorPos,
+                                               cpEnd = (int)SelEndCursorPos;
+
+                                               if (SelBegin.Y > SelRelease.Y) {
+                                                       cpStart = cpEnd;
+                                                       cpEnd = (int)SelStartCursorPos;
+                                               }
+
+                                               if (i == selectionStart.Y) {
+                                                       selRect.Width -= cpStart;
+                                                       selRect.Left += cpStart;
+                                               }
+                                               if (i == selectionEnd.Y)
+                                                       selRect.Width -= (lineLength - cpEnd);
+
+                                               gr.Rectangle (selRect);
+                                               gr.FillPreserve ();
+                                               gr.Save ();
+                                               gr.Clip ();
+                                               gr.SetSourceColor (SelectionForeground);
+                                               gr.MoveTo (lineRect.X, rText.Y + fe.Ascent + (fe.Ascent+fe.Descent) * i);
+                                               gr.ShowText (l);
+                                               gr.Fill ();
+                                               gr.Restore ();
+                                       }
+                               }
+                       }
+               }
+               #endregion
+
+               #region Mouse handling
+               void updatemouseLocalPos(Point mpos){
+                       mouseLocalPos = mpos - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft;
+                       if (mouseLocalPos.X < 0)
+                               mouseLocalPos.X = 0;
+                       if (mouseLocalPos.Y < 0)
+                               mouseLocalPos.Y = 0;
+               }
+               protected override void onFocused (object sender, EventArgs e)
+               {
+                       base.onFocused (sender, e);
+
+                       if (!_selectable)
+                               return;
+                       SelBegin = new Point(0,0);
+                       SelRelease = new Point (lines.LastOrDefault ().Length, lines.Count-1);
+                       RegisterForRedraw ();
+               }
+               protected override void onUnfocused (object sender, EventArgs e)
+               {
+                       base.onUnfocused (sender, e);
+
+                       SelBegin = -1;
+                       SelRelease = -1;
+                       RegisterForRedraw ();
+               }
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseMove (sender, e);
+
+                       if (!(SelectionInProgress && HasFocus && _selectable))
+                               return;
+
+                       updatemouseLocalPos (e.Position);
+
+                       RegisterForRedraw();
+               }
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       if (this.HasFocus && _selectable){
+                               updatemouseLocalPos (e.Position);
+                               SelBegin = -1;
+                               SelRelease = -1;
+                               SelectionInProgress = true;
+                               RegisterForRedraw();//TODO:should put it in properties
+                       }
+
+                       //done at the end to set 'hasFocus' value after testing it
+                       base.onMouseDown (sender, e);
+               }
+               public override void onMouseUp (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseUp (sender, e);
+                       if (!(this.HasFocus || _selectable))
+                               return;
+                       if (!SelectionInProgress)
+                               return;
+
+                       updatemouseLocalPos (e.Position);
+                       SelectionInProgress = false;
+                       RegisterForRedraw ();
+               }
+               public override void onMouseDoubleClick (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseDoubleClick (sender, e);
+                       if (!(this.HasFocus || _selectable))
+                               return;
+                       
+                       GotoWordStart ();
+                       SelBegin = CurrentPosition;
+                       GotoWordEnd ();
+                       SelRelease = CurrentPosition;
+                       SelectionInProgress = false;
+                       RegisterForRedraw ();
+               }
+               #endregion
+
+               /// <summary>
+               /// Update Current Column, line and TextCursorPos
+               /// from mouseLocalPos
+               /// </summary>
+               void computeTextCursor(Context gr)
+               {
+                       TextExtents te;
+
+                       double cPos = 0f;
+
+                       CurrentLine = (int)(mouseLocalPos.Y / (fe.Ascent+fe.Descent));
+
+                       //fix cu
+                       if (CurrentLine >= lines.Count)
+                               CurrentLine = lines.Count - 1;
+
+                       switch (TextAlignment) {
+                       case Alignment.Center:
+                       case Alignment.Top:
+                       case Alignment.Bottom:
+                               cPos+= ClientRectangle.Width - gr.TextExtents(lines [CurrentLine]).Width/2.0;
+                               break;
+                       case Alignment.Right:
+                       case Alignment.TopRight:
+                       case Alignment.BottomRight:
+                               cPos += ClientRectangle.Width - gr.TextExtents(lines [CurrentLine]).Width;
+                               break;
+                       }
+
+                       for (int i = 0; i < lines[CurrentLine].Length; i++)
+                       {
+                               string c = lines [CurrentLine].Substring (i, 1);
+                               if (c == "\t")
+                                       c = new string (' ', Interface.TAB_SIZE);
+
+                               te = gr.TextExtents(c);
+
+                               double halfWidth = te.XAdvance / 2;
+
+                               if (mouseLocalPos.X <= cPos + halfWidth)
+                               {
+                                       CurrentColumn = i;
+                                       textCursorPos = cPos;
+                                       mouseLocalPos = -1;
+                                       return;
+                               }
+
+                               cPos += te.XAdvance;
+                       }
+                       CurrentColumn = lines[CurrentLine].Length;
+                       textCursorPos = cPos;
+
+                       //reset mouseLocalPos
+                       mouseLocalPos = -1;
+               }
+               /// <summary> Computes offsets in cairo units </summary>
+               void computeTextCursorPosition(Context gr)
+               {
+                       if (SelBegin >= 0)
+                               SelStartCursorPos = GetXFromTextPointer (gr, SelBegin);
+                       if (SelRelease >= 0)
+                               SelEndCursorPos = GetXFromTextPointer (gr, SelRelease);
+                       textCursorPos = GetXFromTextPointer (gr, new Point(CurrentColumn, CurrentLine));
+               }
+               /// <summary> Compute x offset in cairo unit from text position </summary>
+               double GetXFromTextPointer(Context gr, Point pos)
+               {
+                       try {
+                               string l = lines [pos.Y].Substring (0, pos.X).
+                                       Replace ("\t", new String (' ', Interface.TAB_SIZE));
+                               return gr.TextExtents (l).XAdvance;
+                       } catch{
+                               return -1;
+                       }
+               }
+    }
+}
diff --git a/Crow/src/Widgets/ListBox.cs b/Crow/src/Widgets/ListBox.cs
new file mode 100644 (file)
index 0000000..438e8d6
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// ListBox.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.Collections;
+using System.Xml.Serialization;
+using System.ComponentModel;
+using System.IO;
+using System.Diagnostics;
+using System.Xml;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Crow
+{
+       public class ListBox : TemplatedGroup
+       {
+               #region CTOR
+               protected ListBox () : base(){}
+               public ListBox (Interface iface) : base(iface) {}
+               #endregion
+
+       }
+}
+
diff --git a/Crow/src/Widgets/Menu.cs b/Crow/src/Widgets/Menu.cs
new file mode 100644 (file)
index 0000000..85f5485
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Menu.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       public class Menu : TemplatedGroup
+       {
+               #region CTOR
+               protected Menu () : base(){}
+               public Menu (Interface iface) : base(iface) {}
+               #endregion
+
+               Orientation orientation;
+               bool autoOpen = false;
+
+               #region Public properties
+               [DefaultValue(Orientation.Horizontal)]
+               public Orientation Orientation {
+                       get { return orientation; }
+                       set {
+                               if (orientation == value)
+                                       return;
+                               orientation = value;
+                               NotifyValueChanged ("Orientation", orientation);
+                       }
+               }
+               [XmlIgnore]public bool AutomaticOpening
+               {
+                       get { return autoOpen; }
+                       set     {
+                               if (autoOpen == value)
+                                       return;
+                               autoOpen = value;
+                               NotifyValueChanged ("AutomaticOpening", autoOpen);
+                       }
+               }
+               #endregion
+
+               public override void AddItem (Widget g)
+               {                       
+                       base.AddItem (g);
+
+                       if (orientation == Orientation.Horizontal)
+                               g.NotifyValueChanged ("PopDirection", Alignment.Bottom);
+                       else
+                               g.NotifyValueChanged ("PopDirection", Alignment.Right);
+               }
+               public override void onMouseLeave (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseLeave (sender, e);
+                       AutomaticOpening = false;
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/MenuItem.cs b/Crow/src/Widgets/MenuItem.cs
new file mode 100644 (file)
index 0000000..abc9d11
--- /dev/null
@@ -0,0 +1,196 @@
+//
+// MenuItem.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       public class MenuItem : Menu
+       {
+               #region CTOR
+               protected MenuItem () : base(){}
+               public MenuItem (Interface iface) : base(iface) {}
+               #endregion
+
+               public event EventHandler Open;
+               public event EventHandler Close;
+
+               Command command;
+               Picture icon;
+               bool isOpened;
+               Measure popWidth, popHeight;
+
+               #region Public properties
+               [DefaultValue(false)]
+               public bool IsOpened {
+                       get { return isOpened; }
+                       set {
+                               if (isOpened == value)
+                                       return;
+                               isOpened = value;
+                               NotifyValueChanged ("IsOpened", isOpened);
+
+                               if (isOpened) {
+                                       onOpen (this, null);
+                                       if (LogicalParent is Menu)
+                                               (LogicalParent as Menu).AutomaticOpening = true;
+                               }else
+                                       onClose (this, null);
+                       }
+               }
+               [DefaultValue(null)]
+               public virtual Command Command {
+                       get { return command; }
+                       set {
+                               if (command == value)
+                                       return;
+
+                               if (command != null) {
+                                       command.raiseAllValuesChanged ();
+                                       command.ValueChanged -= Command_ValueChanged;
+                               }
+
+                               command = value;
+
+                               if (command != null) {
+                                       command.ValueChanged += Command_ValueChanged;
+                                       command.raiseAllValuesChanged ();
+                               }
+
+                               NotifyValueChanged ("Command", command);
+                       }
+               }
+               
+               public override bool IsEnabled {
+                       get { return Command == null ? base.IsEnabled : Command.CanExecute; }
+                       set { base.IsEnabled = value; }
+               }
+               
+               public override string Caption {
+                       get { return Command == null ? base.Caption : Command.Caption; }
+                       set { base.Caption = value; }
+               }
+               
+               public Picture Icon {
+                       get { return Command == null ? icon : Command.Icon;; }
+                       set {
+                               if (icon == value)
+                                       return;
+                               icon = value;
+                               if (command == null)
+                                       NotifyValueChanged ("Icon", icon);
+                       }
+               }
+               [DefaultValue("Fit")]
+               public virtual Measure PopWidth {
+                       get { return popWidth; }
+                       set {
+                               if (popWidth == value)
+                                       return;
+                               popWidth = value;
+                               NotifyValueChanged ("PopWidth", popWidth);
+                       }
+               }
+               [DefaultValue("Fit")]
+               public virtual Measure PopHeight {
+                       get { return popHeight; }
+                       set {
+                               if (popHeight == value)
+                                       return;
+                               popHeight = value;
+                               NotifyValueChanged ("PopHeight", popHeight);
+                       }
+               }
+               #endregion
+
+               public override void AddItem (Widget g)
+               {
+                       base.AddItem (g);
+                       g.NotifyValueChanged ("PopDirection", Alignment.Right);
+               }
+
+               void Command_ValueChanged (object sender, ValueChangeEventArgs e)
+               {
+                       string mName = e.MemberName;
+                       if (mName == "CanExecute")
+                               mName = "IsEnabled";
+                       NotifyValueChanged (mName, e.NewValue);
+               }
+               protected virtual void onOpen (object sender, EventArgs e){
+                       Open.Raise (this, null);
+               }
+               protected virtual void onClose (object sender, EventArgs e){
+                       System.Diagnostics.Debug.WriteLine ("close: " + this.ToString());
+                       Close.Raise (this, null);
+               }
+               public override bool MouseIsIn (Point m)
+               {
+                       return IsEnabled && !IsDragged ? base.MouseIsIn (m) || child.MouseIsIn (m) : false;
+               }
+               public override void onMouseEnter (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseEnter (sender, e);
+                       Menu menu = LogicalParent as Menu;
+                       if (menu == null)
+                               return;
+                       if (menu.AutomaticOpening && items.Children.Count>0)
+                               IsOpened = true;
+               }
+               public override void onMouseLeave (object sender, MouseMoveEventArgs e)
+               {
+                       if (IsOpened)
+                               IsOpened = false;
+                       base.onMouseLeave (this, e);
+               }
+               public override void onMouseClick (object sender, MouseButtonEventArgs e)
+               {
+#if DEBUG_FOCUS
+                       System.Diagnostics.Debug.WriteLine ("MENU CLICK => " + this.ToString ());
+#endif
+                       if (command != null) {
+                               command.Execute ();
+                               closeMenu ();
+                       }
+                       if (hasClick)
+                               base.onMouseClick (sender, e);
+
+                       if (!IsOpened)
+                               (LogicalParent as Menu).AutomaticOpening = false;
+               }
+               void closeMenu () {
+                       MenuItem tmp = LogicalParent as MenuItem;
+                       while (tmp != null) {
+                               tmp.IsOpened = false;
+                               tmp.Background = Color.Transparent;
+                               tmp.AutomaticOpening = false;
+                               tmp = tmp.LogicalParent as MenuItem;
+                       }
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/MessageBox.cs b/Crow/src/Widgets/MessageBox.cs
new file mode 100644 (file)
index 0000000..e5746c6
--- /dev/null
@@ -0,0 +1,203 @@
+//
+// MessageBox.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       public class MessageBox : Window
+       {
+               #region CTOR
+               protected MessageBox () : base(){}
+               public MessageBox (Interface iface) : base(iface){}
+               #endregion
+
+               public enum Type {
+                       None,
+                       Information,
+                       Alert,
+                       Error,
+                       YesNo,
+                       YesNoCancel,
+
+               }
+
+               protected override void loadTemplate (Widget template)
+               {
+                       base.loadTemplate (template);
+                       NotifyValueChanged ("MsgIcon", "#Crow.Icons.iconInfo.svg");
+               }
+               string message, okMessage, cancelMessage, noMessage;
+               Type msgType = Type.None;
+
+               public event EventHandler Yes;
+               public event EventHandler No;
+               public event EventHandler Cancel;
+
+               [DefaultValue("Informations")]
+               public virtual string Message
+               {
+                       get { return message; }
+                       set {
+                               if (message == value)
+                                       return;
+                               message = value;
+                               NotifyValueChanged ("Message", message);
+                       }
+               }
+               [DefaultValue("Ok")]
+               public virtual string OkMessage
+               {
+                       get { return okMessage; }
+                       set {
+                               if (okMessage == value)
+                                       return;
+                               okMessage = value;
+                               NotifyValueChanged ("OkMessage", okMessage);
+                       }
+               }
+               [DefaultValue("Cancel")]
+               public virtual string CancelMessage
+               {
+                       get { return cancelMessage; }
+                       set {
+                               if (cancelMessage == value)
+                                       return;
+                               cancelMessage = value;
+                               NotifyValueChanged ("CancelMessage", cancelMessage);
+                       }
+               }
+               [DefaultValue("No")]
+               public virtual string NoMessage
+               {
+                       get { return noMessage; }
+                       set {
+                               if (noMessage == value)
+                                       return;
+                               noMessage = value;
+                               NotifyValueChanged ("NoMessage", noMessage);
+                       }
+               }
+               [DefaultValue("Information")]
+               public virtual Type MsgType
+               {
+                       get { return msgType; }
+                       set {
+                               if (msgType == value)
+                                       return;
+                               msgType = value;
+                               NotifyValueChanged ("MsgType", msgType);
+                               switch (msgType) {
+                               case Type.Information:
+                                       MsgIcon = "#Crow.Icons.iconInfo.svg";
+                                       Caption = "Informations";
+                                       OkMessage = "Ok";
+                                       NotifyValueChanged ("CancelButIsVisible", false);
+                                       NotifyValueChanged ("NoButIsVisible", false);
+                                       break;
+                               case Type.YesNo:
+                               case Type.YesNoCancel:
+                                       MsgIcon = "#Crow.Icons.question.svg";
+                                       Caption = "Choice";
+                                       OkMessage = "Yes";
+                                       NoMessage = "No";
+                                       NotifyValueChanged ("CancelButIsVisible", msgType == Type.YesNoCancel);
+                                       NotifyValueChanged ("NoButIsVisible", true);
+                                       break;
+                               case Type.Alert:
+                                       MsgIcon = "#Crow.Icons.IconAlerte.svg";
+                                       Caption = "Alert";
+                                       OkMessage = "Ok";
+                                       CancelMessage = "Cancel";
+                                       NotifyValueChanged ("CancelButIsVisible", true);
+                                       NotifyValueChanged ("NoButIsVisible", false);
+                                       break;
+                               case Type.Error:
+                                       MsgIcon = "#Crow.Icons.exit.svg";
+                                       Caption = "Error";
+                                       OkMessage = "Ok";
+                                       NotifyValueChanged ("CancelButIsVisible", false);
+                                       NotifyValueChanged ("NoButIsVisible", false);
+                                       break;
+                               }
+                       }
+               }
+
+               string msgIcon = null;
+               public string MsgIcon {
+                       get { return msgIcon; }
+                       set {
+                               if (value == MsgIcon)
+                                       return;
+                               msgIcon = value;
+                               NotifyValueChanged ("MsgIcon", MsgIcon);
+                       }
+               }
+               void onOkButtonClick (object sender, EventArgs e)
+               {
+                       Yes.Raise (this, null);
+                       close ();
+               }
+               void onNoButtonClick (object sender, EventArgs e)
+               {
+                       No.Raise (this, null);
+                       close ();
+               }
+               void onCancelButtonClick (object sender, EventArgs e)
+               {
+                       Cancel.Raise (this, null);
+                       close ();
+               }
+               public static MessageBox Show (Interface iface, Type msgBoxType, string message, string okMsg = "", string cancelMsg = ""){
+                       lock (iface.UpdateMutex) {
+                               MessageBox mb = new MessageBox (iface);
+                               mb.IFace.AddWidget (mb);
+                               mb.MsgType = msgBoxType;
+                               mb.Message = message;
+                               if (!string.IsNullOrEmpty(okMsg))
+                                       mb.OkMessage = okMsg;
+                               if (!string.IsNullOrEmpty(cancelMsg))
+                                       mb.CancelMessage = cancelMsg;
+                               return mb;
+                       }
+               }
+               public static MessageBox ShowModal (Interface iface, Type msgBoxType, string message){
+                       lock (iface.UpdateMutex) {
+                               MessageBox mb = new MessageBox (iface) {
+                                       Modal = true,
+                                       MsgType = msgBoxType,
+                                       Message = message
+                               };
+
+                               iface.AddWidget (mb);
+                               return mb;
+                       }
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/NumericControl.cs b/Crow/src/Widgets/NumericControl.cs
new file mode 100644 (file)
index 0000000..ec63fe8
--- /dev/null
@@ -0,0 +1,142 @@
+//
+// NumericControl.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       public abstract class NumericControl : TemplatedControl
+       {
+               #region CTOR
+               protected NumericControl () : base(){}
+               public NumericControl (Interface iface) : base(iface)
+               {
+               }
+//             public NumericControl(double minimum, double maximum, double step)
+//                     : base()
+//             {
+//             }
+               #endregion
+
+               #region protected fields
+               protected double _actualValue, minValue, maxValue, smallStep, bigStep;
+               protected int _decimals;
+               #endregion
+
+               #region public properties
+               [DefaultValue(2)]
+               public int Decimals
+               {
+                       get { return _decimals; }
+                       set
+                       {
+                               if (value == _decimals)
+                                       return;
+                               _decimals = value;
+                               NotifyValueChanged("Decimals",  _decimals);
+                               RegisterForGraphicUpdate();
+                       }
+               }
+               [DefaultValue(0.0)]
+               public virtual double Minimum {
+                       get { return minValue; }
+                       set {
+                               if (minValue == value)
+                                       return;
+
+                               minValue = value;
+                               NotifyValueChanged ("Minimum", minValue);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(100.0)]
+               public virtual double Maximum
+               {
+                       get { return maxValue; }
+                       set {
+                               if (maxValue == value)
+                                       return;
+
+                               maxValue = value;
+                               NotifyValueChanged ("Maximum", maxValue);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(1.0)]
+               public virtual double SmallIncrement
+               {
+                       get { return smallStep; }
+                       set {
+                               if (smallStep == value)
+                                       return;
+
+                               smallStep = value;
+                               NotifyValueChanged ("SmallIncrement", smallStep);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(5.0)]
+               public virtual double LargeIncrement
+               {
+                       get { return bigStep; }
+                       set {
+                               if (bigStep == value)
+                                       return;
+
+                               bigStep = value;
+                               NotifyValueChanged ("LargeIncrement", bigStep);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(0.0)]
+               public virtual double Value
+               {
+                       get { return _actualValue; }
+                       set
+                       {
+                               if (value == _actualValue)
+                                       return;
+
+                               if (value < minValue)
+                                       _actualValue = minValue;
+                               else if (value > maxValue)
+                                       _actualValue = maxValue;
+                               else                    
+                                       _actualValue = value;
+
+                               _actualValue = Math.Round (_actualValue, _decimals);
+
+                               NotifyValueChanged("Value",  _actualValue);
+                               RegisterForGraphicUpdate();
+                       }
+               }
+               #endregion
+
+       }
+}
+
diff --git a/Crow/src/Widgets/Popper.cs b/Crow/src/Widgets/Popper.cs
new file mode 100644 (file)
index 0000000..b6acabd
--- /dev/null
@@ -0,0 +1,250 @@
+//
+// Popper.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+    public class Popper : TemplatedContainer
+    {
+               #region CTOR
+               protected Popper () : base(){}
+               public Popper (Interface iface) : base(iface){}
+               #endregion
+
+               bool _isPopped, _canPop;
+               Alignment popDirection;
+               Widget _content;
+               Measure popWidth, popHeight;
+
+               public event EventHandler Popped;
+               public event EventHandler Unpoped;
+
+               #region Public Properties
+               [DefaultValue("Fit")]
+               public virtual Measure PopWidth {
+                       get { return popWidth; }
+                       set {
+                               if (popWidth == value)
+                                       return;
+                               popWidth = value;
+                               NotifyValueChanged ("PopWidth", popWidth);
+                       }
+               }
+               [DefaultValue("Fit")]
+               public virtual Measure PopHeight {
+                       get { return popHeight; }
+                       set {
+                               if (popHeight == value)
+                                       return;
+                               popHeight = value;
+                               NotifyValueChanged ("PopHeight", popHeight);
+                       }
+               }
+               [DefaultValue(false)]
+               public bool IsPopped
+               {
+                       get { return _isPopped; }
+                       set
+                       {
+                               if (!_canPop & value)
+                                       return;                                 
+                               
+                               if (value == _isPopped)
+                                       return;
+
+                               _isPopped = value;
+
+                               NotifyValueChanged ("IsPopped", _isPopped);
+
+                               if (_isPopped)
+                                       onPop (this, null);
+                               else
+                                       onUnpop (this, null);
+
+                       }
+               }
+               [DefaultValue(true)]
+               public bool CanPop
+               {
+                       get { return _canPop; }
+                       set
+                       {
+                               if (value == _canPop)
+                                       return;
+
+                               _canPop = value;
+                               NotifyValueChanged ("CanPop", _canPop);
+                       }
+               }
+               [DefaultValue(Alignment.Bottom)]
+               public virtual Alignment PopDirection {
+                       get { return popDirection; }
+                       set {
+                               if (popDirection == value)
+                                       return;
+                               popDirection = value;
+                               NotifyValueChanged ("PopDirection", popDirection);
+                       }
+               }
+               #endregion
+
+               public override Widget Content {
+                       get { return _content; }
+                       set {
+                               if (_content != null) {
+                                       _content.LogicalParent = null;
+                                       //_content.isPopup = false;
+                                       _content.LayoutChanged -= _content_LayoutChanged;
+                               }
+
+                               _content = value;
+
+                               if (_content == null)
+                                       return;
+
+                               _content.LogicalParent = this;
+                               //_content.isPopup = true;
+                               _content.HorizontalAlignment = HorizontalAlignment.Left;
+                               _content.VerticalAlignment = VerticalAlignment.Top;
+                               _content.LayoutChanged += _content_LayoutChanged;
+                       }
+               }
+               void positionContent(LayoutingType lt){
+                       ILayoutable tc = Content.Parent;
+                       if (tc == null)
+                               return;
+                       Rectangle r = this.ScreenCoordinates (this.Slot);
+                       if (lt == LayoutingType.X) {
+                               if (popDirection.HasFlag (Alignment.Right)) {
+                                       if (r.Right + Content.Slot.Width > tc.ClientRectangle.Right)
+                                               Content.Left = r.Left - Content.Slot.Width;
+                                       else
+                                               Content.Left = r.Right;
+                               } else if (popDirection.HasFlag (Alignment.Left)) {
+                                       if (r.Left - Content.Slot.Width < tc.ClientRectangle.Left)
+                                               Content.Left = r.Right;
+                                       else
+                                               Content.Left = r.Left - Content.Slot.Width;
+                               } else {
+                                       if (Content.Slot.Width < tc.ClientRectangle.Width) {
+                                               if (r.Left + Content.Slot.Width > tc.ClientRectangle.Right)
+                                                       Content.Left = tc.ClientRectangle.Right - Content.Slot.Width;
+                                               else
+                                                       Content.Left = r.Left;
+                                       } else
+                                               Content.Left = 0;
+                               }
+                       }else if (lt == LayoutingType.Y) {
+                               if (Content.Slot.Height < tc.ClientRectangle.Height) {
+                                       if (PopDirection.HasFlag (Alignment.Bottom)) {
+                                               if (r.Bottom + Content.Slot.Height > tc.ClientRectangle.Bottom)
+                                                       Content.Top = r.Top - Content.Slot.Height;
+                                               else
+                                                       Content.Top = r.Bottom;
+                                       } else if (PopDirection.HasFlag (Alignment.Top)) {
+                                               if (r.Top - Content.Slot.Height < tc.ClientRectangle.Top)
+                                                       Content.Top = r.Bottom;
+                                               else
+                                                       Content.Top = r.Top - Content.Slot.Height;
+                                       } else
+                                               Content.Top = r.Top;
+                               }else
+                                       Content.Top = 0;
+                       }
+               }
+               protected void _content_LayoutChanged (object sender, LayoutingEventArgs e)
+               {
+                       if (e.LayoutType.HasFlag (LayoutingType.Width))
+                               positionContent (LayoutingType.X);
+                       if (e.LayoutType.HasFlag(LayoutingType.Height))
+                               positionContent (LayoutingType.Y);
+               }
+
+               #region GraphicObject overrides
+               public override void onMouseLeave (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseLeave (this, e);
+                       IsPopped = false;
+               }
+               public override bool MouseIsIn (Point m)
+               {                       
+                       if (Content?.Parent != null)
+                               if (Content.MouseIsIn (m))
+                                       return true;
+                       return base.MouseIsIn (m);
+               }
+               public override void checkHoverWidget (MouseMoveEventArgs e)
+               {
+                       if (IFace.HoverWidget != this) {
+                               IFace.HoverWidget = this;
+                               onMouseEnter (this, e);
+                       }
+                       if (Content != null){
+                               if (Content.Parent != null) {
+                                       if (Content.MouseIsIn (e.Position)) {
+                                               Content.checkHoverWidget (e);
+                                               return;
+                                       }
+                               }
+                       }
+                       base.checkHoverWidget (e);
+               }
+               #endregion
+
+               public virtual void onPop(object sender, EventArgs e)
+               {
+                       if (Content != null) {
+                               Content.Visible = true;
+                               if (Content.Parent == null)
+                                       IFace.AddWidget (Content);
+                               //if (Content.LogicalParent != this)
+                               Content.LogicalParent = this;
+                               IFace.PutOnTop (Content, true);
+                               _content_LayoutChanged (this, new LayoutingEventArgs (LayoutingType.Sizing));
+                       }
+                       Popped.Raise (this, e);
+               }
+               public virtual void onUnpop(object sender, EventArgs e)
+               {
+                       if (Content != null) {
+                               Content.Visible = false;
+                       }
+                       Unpoped.Raise (this, e);
+               }
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (_content != null && disposing) {
+                               if (_content.Parent == null)
+                                       _content.Dispose ();
+                       }
+                       base.Dispose (disposing);
+               }
+       }
+}
diff --git a/Crow/src/Widgets/PrivateContainer.cs b/Crow/src/Widgets/PrivateContainer.cs
new file mode 100644 (file)
index 0000000..7909a6d
--- /dev/null
@@ -0,0 +1,245 @@
+//
+// PrivateContainer.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.Xml.Serialization;
+using System.ComponentModel;
+using Crow.Cairo;
+
+namespace Crow
+{
+       /// <summary>
+       /// Implement drawing and layouting for a single child, but
+       /// does not expose child to allow reuse of container
+       /// behaviour for widgets that have other xml hierarchy: example
+       /// TemplatedControl may have 3 children (template,templateItem,content) but
+       /// behave exactely as a container for layouting and drawing
+       /// </summary>
+       [DesignIgnore]
+       public class PrivateContainer : Widget
+       {
+               #region CTOR
+               protected PrivateContainer () : base(){}
+               public PrivateContainer (Interface iface) : base(iface){}
+               #endregion
+
+               #if DESIGN_MODE
+               public override bool FindByDesignID(string designID, out Widget go){
+                       go = null;
+                       if (base.FindByDesignID (designID, out go))
+                               return true;
+                       if (child == null)
+                               return false;
+                       return child.FindByDesignID (designID, out go);                                 
+               }
+               #endif
+               protected Widget child;
+               #if DEBUG_LOG
+               internal GraphicObject getTemplateRoot {
+                       get { return child; }
+               }
+               #endif
+
+               protected virtual void SetChild(Widget _child)
+               {
+
+                       if (child != null) {
+                               //check if HoverWidget is removed from Tree
+                               if (IFace.HoverWidget != null) {
+                                       if (this.Contains (IFace.HoverWidget))
+                                               IFace.HoverWidget = null;
+                               }
+                               contentSize = default(Size);
+                               child.LayoutChanged -= OnChildLayoutChanges;
+                               this.RegisterForGraphicUpdate ();
+                               child.Dispose ();
+                       }
+
+                       child = _child as Widget;
+
+                       if (child != null) {
+                               child.Parent = this;
+                               child.LayoutChanged += OnChildLayoutChanges;
+                               contentSize = child.Slot.Size;
+                               child.RegisteredLayoutings = LayoutingType.None;
+                               child.RegisterForLayouting (LayoutingType.Sizing);
+                       }
+               }
+               //dispose child if not null
+               protected virtual void deleteChild () {
+                       Widget g = child;
+                       SetChild (null);
+                       if (g != null)
+                               g.Dispose ();
+               }
+
+               #region GraphicObject Overrides
+
+               public override Widget FindByName (string nameToFind)
+               {
+                       if (Name == nameToFind)
+                               return this;
+
+                       return child == null ? null : child.FindByName (nameToFind);
+               }
+               public override bool Contains (Widget goToFind)
+               {
+                       return child == goToFind ? true : 
+                               child == null ? false : child.Contains(goToFind);
+               }
+               public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
+               {
+                       base.OnDataSourceChanged (this, e);
+                       if (child != null)
+                       if (child.localDataSourceIsNull & child.localLogicalParentIsNull)
+                               child.OnDataSourceChanged (child, e);
+               }
+               public override bool UpdateLayout (LayoutingType layoutType)
+               {
+                       if (child != null) {
+                               //force sizing to fit if sizing on children and child has stretched size
+                               switch (layoutType) {
+                               case LayoutingType.Width:
+                                       if (Width == Measure.Fit && child.Width.IsRelativeToParent)
+                                               child.Width = Measure.Fit;
+                                       break;
+                               case LayoutingType.Height:
+                                       if (Height == Measure.Fit && child.Height.IsRelativeToParent)
+                                               child.Height = Measure.Fit;
+                                       break;
+                               }
+                       }
+                       return base.UpdateLayout (layoutType);
+               }
+               public override void OnLayoutChanges (LayoutingType layoutType)
+               {
+                       base.OnLayoutChanges (layoutType);
+
+                       if (child == null)
+                               return;
+                       
+                       LayoutingType ltChild = LayoutingType.None;
+
+                       if (layoutType == LayoutingType.Width) {
+                               if (child.Width.IsRelativeToParent) {
+                                       ltChild |= LayoutingType.Width;
+                                       if (child.Width.Value < 100 && child.Left == 0)
+                                               ltChild |= LayoutingType.X;
+                               } else if (child.Left == 0)
+                                       ltChild |= LayoutingType.X;
+                       } else if (layoutType == LayoutingType.Height) {
+                               if (child.Height.IsRelativeToParent) {
+                                       ltChild |= LayoutingType.Height;
+                                       if (child.Height.Value < 100 && child.Top == 0)
+                                               ltChild |= LayoutingType.Y;
+                               } else if (child.Top == 0)
+                                               ltChild |= LayoutingType.Y;
+                       }
+                       if (ltChild == LayoutingType.None)
+                               return;
+                       child.RegisterForLayouting (ltChild);
+               }
+               public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
+               {                       
+                       Widget g = sender as Widget;
+
+                       if (arg.LayoutType == LayoutingType.Width) {
+                               if (Width != Measure.Fit)
+                                       return;
+                               contentSize.Width = g.Slot.Width;
+                               this.RegisterForLayouting (LayoutingType.Width);
+                       }else if (arg.LayoutType == LayoutingType.Height){
+                               if (Height != Measure.Fit)
+                                       return;
+                               contentSize.Height = g.Slot.Height;
+                               this.RegisterForLayouting (LayoutingType.Height);
+                       }
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       gr.Save ();
+
+                       if (ClipToClientRect) {
+                               //clip to client zone
+                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
+                               gr.Clip ();
+                       }
+
+                       if (child != null) {
+                               if (child.Visible)
+                                       child.Paint (ref gr);
+                       }
+                       gr.Restore ();
+               }
+               protected override void UpdateCache (Context ctx)
+               {
+                       Rectangle rb = Slot + Parent.ClientRectangle.Position;
+
+
+                       Context gr = new Context (bmp);
+
+                       if (!Clipping.IsEmpty) {
+                               for (int i = 0; i < Clipping.NumRectangles; i++)
+                                       gr.Rectangle(Clipping.GetRectangle(i));
+                               gr.ClipPreserve();
+                               gr.Operator = Operator.Clear;
+                               gr.Fill();
+                               gr.Operator = Operator.Over;
+
+                               onDraw (gr);
+                       }
+                               
+                       gr.Dispose ();
+
+                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
+                       ctx.Paint ();
+                       Clipping.Dispose();
+                       Clipping = new Region ();
+               }
+               #endregion
+
+               #region Mouse handling
+               public override void checkHoverWidget (MouseMoveEventArgs e)
+               {
+                       base.checkHoverWidget (e);
+
+                       if (child != null) 
+                               if (child.MouseIsIn (e.Position)) 
+                                       child.checkHoverWidget (e);
+               }
+               #endregion
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (disposing && child != null)
+                               child.Dispose ();
+                       base.Dispose (disposing);
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/ProgressBar.cs b/Crow/src/Widgets/ProgressBar.cs
new file mode 100644 (file)
index 0000000..20fadad
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// ProgressBar.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.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crow.Cairo;
+using System.Diagnostics;
+using System.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       
+       public class ProgressBar : NumericControl
+    {
+               #region CTOR
+               protected ProgressBar () : base(){}
+               public ProgressBar(Interface iface) : base(iface){}
+               #endregion
+
+               protected override void loadTemplate (Widget template)
+               {
+                       
+               }
+
+               #region GraphicObject overrides
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       if (Maximum == 0)
+                               return;
+
+                       Rectangle rBack = ClientRectangle;
+                       rBack.Width = (int)((double)rBack.Width / Maximum * Value);
+                       Foreground.SetAsSource (gr, rBack);
+
+                       CairoHelpers.CairoRectangle(gr,rBack,CornerRadius);
+                       gr.Fill();
+               }
+               #endregion
+    }
+}
diff --git a/Crow/src/Widgets/RadioButton.cs b/Crow/src/Widgets/RadioButton.cs
new file mode 100644 (file)
index 0000000..d18971a
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// RadioButton.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.ComponentModel;
+using System.Xml.Serialization;
+
+namespace Crow
+{
+    public class RadioButton : TemplatedControl
+    {                  
+               bool isChecked;
+
+               #region CTOR
+               protected RadioButton () : base(){}
+               public RadioButton(Interface iface) : base(iface){}     
+               #endregion
+
+               public event EventHandler Checked;
+               public event EventHandler Unchecked;
+
+               #region GraphicObject overrides
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {                                               
+                       Group pg = Parent as Group;
+                       if (pg != null) {
+                               for (int i = 0; i < pg.Children.Count; i++) {
+                                       RadioButton c = pg.Children [i] as RadioButton;
+                                       if (c == null)
+                                               continue;
+                                       c.IsChecked = (c == this);
+                               }
+                       } else
+                               IsChecked = !IsChecked;
+
+                       base.onMouseDown (sender, e);
+               }
+               #endregion
+
+        [DefaultValue(false)]
+        public bool IsChecked
+        {
+                       get { return isChecked; }
+            set
+            {
+                               if (isChecked == value)
+                                       return;
+                               
+                               isChecked = value;
+
+                               NotifyValueChanged ("IsChecked", value);
+
+                               if (isChecked)
+                                       Checked.Raise (this, null);
+                               else
+                                       Unchecked.Raise (this, null);
+            }
+        }
+       }
+}
diff --git a/Crow/src/Widgets/SaturationValueSelector.cs b/Crow/src/Widgets/SaturationValueSelector.cs
new file mode 100644 (file)
index 0000000..779a6de
--- /dev/null
@@ -0,0 +1,150 @@
+//
+// SaturationValueSelector.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 Crow.Cairo;
+using System.Xml.Serialization;
+
+namespace Crow
+{
+       [DesignIgnore]
+       public class SaturationValueSelector : ColorSelector
+       {
+               public SaturationValueSelector () : base(){}
+               public SaturationValueSelector (Interface iface) : base(iface)
+               {
+               }
+
+               double v, s;
+                               
+               public virtual double V {
+                       get { return v; }
+                       set {
+                               if (v == value)
+                                       return;
+                               v = value;
+                               NotifyValueChanged ("V", v);
+                               mousePos.Y = (int)Math.Floor((1.0-v) * (double)ClientRectangle.Height);
+
+                               RegisterForRedraw ();
+                       }
+               }
+               
+               public virtual double S {
+                       get { return s; }
+                       set {
+                               if (s == value)
+                                       return;
+                               s = value;
+                               NotifyValueChanged ("S", s);
+                               mousePos.X = (int)Math.Floor(s * (double)ClientRectangle.Width);
+
+                               RegisterForRedraw ();
+                       }
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       Rectangle r = ClientRectangle;
+
+                       if (Foreground != null) {//TODO:test if null should be removed
+                               Foreground.SetAsSource (gr, r);
+                               CairoHelpers.CairoRectangle (gr, r, CornerRadius);
+                               gr.Fill ();
+                       }
+
+                       Crow.Gradient grad = new Gradient (Gradient.Type.Horizontal);
+                       grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 1, 1, 1)));
+                       grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, 1, 1, 0)));
+                       grad.SetAsSource (gr, r);
+                       CairoHelpers.CairoRectangle (gr, r, CornerRadius);
+                       gr.Fill();
+                       grad = new Gradient (Gradient.Type.Vertical);
+                       grad.Stops.Add (new Gradient.ColorStop (0, new Color (0, 0, 0, 0)));
+                       grad.Stops.Add (new Gradient.ColorStop (1, new Color (0, 0, 0, 1)));
+                       grad.SetAsSource (gr, r);
+                       CairoHelpers.CairoRectangle (gr, r, CornerRadius);
+                       gr.Fill();
+
+
+                       gr.Arc (mousePos.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
+                       gr.SetSourceColor (Color.Black);
+                       gr.LineWidth = 2.0;
+                       gr.StrokePreserve ();
+                       gr.SetSourceColor (Color.White);
+                       gr.LineWidth = 1.0;
+                       gr.Stroke ();
+               }
+
+               //public override void Paint (ref Context ctx)
+               //{
+               //      base.Paint (ref ctx);
+
+               //      Rectangle rb = Slot + Parent.ClientRectangle.Position;
+               //      ctx.Save ();
+
+               //      ctx.Translate (rb.X, rb.Y);
+
+               //      ctx.SetSourceColor (Color.DimGrey);
+               //      ctx.Arc (mousePos.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
+               //      ctx.LineWidth = 0.5;
+               //      ctx.Stroke ();
+               //      ctx.Translate (-0.5, -0.5);
+               //      ctx.Arc (mousePos.X, mousePos.Y, 3.5, 0, Math.PI * 2.0);
+               //      ctx.SetSourceColor (Color.White);
+               //      ctx.Stroke ();
+
+               //      ctx.Restore ();
+               //}
+
+               protected override void updateMouseLocalPos (Point mPos)
+               {
+                       base.updateMouseLocalPos (mPos);
+
+                       Rectangle cb = ClientRectangle;
+                       s = (double)mousePos.X / (double)cb.Width;
+                       v = 1.0 - (double)mousePos.Y / (double)cb.Height;
+                       NotifyValueChanged ("S", s);
+                       NotifyValueChanged ("V", v);
+
+                       RegisterForRedraw ();
+               }
+               public override void OnLayoutChanges (LayoutingType layoutType)
+               {
+                       base.OnLayoutChanges (layoutType);
+                       switch (layoutType) {
+                       case LayoutingType.Width:
+                               mousePos.X = (int)Math.Floor(s * (double)ClientRectangle.Width);
+                               break;
+                       case LayoutingType.Height:
+                               mousePos.Y = (int)Math.Floor((1.0-v) * (double)ClientRectangle.Height);
+                               break;
+                       }
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/ScrollBar.cs b/Crow/src/Widgets/ScrollBar.cs
new file mode 100644 (file)
index 0000000..cf6201e
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// ScrollBar.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       /// <summary>
+       /// templeted numeric control
+       /// </summary>
+       public class ScrollBar : NumericControl
+       {
+               //TODO:could be replaced by a template for a Slider
+
+               Orientation _orientation;
+               int _cursorSize;
+
+               #region CTOR
+               protected ScrollBar () : base(){}
+               public ScrollBar(Interface iface) : base(iface) {}
+               #endregion
+
+               [DefaultValue(Orientation.Vertical)]
+               public virtual Orientation Orientation
+               {
+                       get { return _orientation; }
+                       set {                           
+                               if (_orientation == value)
+                                       return;
+                               _orientation = value;
+                               NotifyValueChanged ("Orientation", _orientation);
+                               if (_orientation == Orientation.Horizontal)
+                                       NotifyValueChanged ("ScrollBackShape", "M 1.5,3.5 L 6.5,0.5 L 6.5,6.5 Z");
+                               else
+                                       NotifyValueChanged ("ScrollBackShape", "M 4.5,0.5 L 9.5,9.5 L 0.5,9.5 Z");
+
+                RegisterForGraphicUpdate ();
+                       }
+               }
+               [DefaultValue(20)]
+               public virtual int CursorSize {
+                       get { return _cursorSize; }
+                       set {
+                               if (_cursorSize == value)
+                                       return;
+                               _cursorSize = value;
+                               RegisterForGraphicUpdate ();
+                               NotifyValueChanged ("CursorSize", _cursorSize);
+                       }
+               }
+               public void onScrollBack (object sender, MouseButtonEventArgs e)
+               {
+                       Value -= SmallIncrement;
+               }
+               public void onScrollForth (object sender, MouseButtonEventArgs e)
+               {
+                       Value += SmallIncrement;
+               }
+
+               public void onSliderValueChange(object sender, ValueChangeEventArgs e){
+                       if (e.MemberName == "Value")
+                               Value = Convert.ToDouble(e.NewValue);
+               }
+       }
+}
diff --git a/Crow/src/Widgets/Scroller.cs b/Crow/src/Widgets/Scroller.cs
new file mode 100644 (file)
index 0000000..7bdb7d3
--- /dev/null
@@ -0,0 +1,292 @@
+//
+// Scroller.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.Xml.Serialization;
+using System.ComponentModel;
+using System.Diagnostics;
+using Crow.Cairo;
+
+namespace Crow
+{
+       /// <summary>
+       /// scrolling surface, to be contained in a smaller container in which it will be scrolled
+       /// </summary>
+       public class Scroller : Container
+       {
+               #region CTOR
+               protected Scroller () : base(){}
+               public Scroller (Interface iface) : base(iface){}
+               #endregion
+
+               //public event EventHandler<ScrollingEventArgs> Scrolled;
+
+               int scrollX, scrollY, maxScrollX, maxScrollY, scrollSpeed;
+
+               /// <summary>
+               /// if true, key stroke are handled in derrived class
+               /// </summary>
+               protected bool KeyEventsOverrides = false;
+
+               #region public properties
+               /// <summary> Horizontal Scrolling Position </summary>
+               [DefaultValue(0)]
+               public virtual int ScrollX {
+                       get { return scrollX; }
+                       set {
+                               if (scrollX == value)
+                                       return;
+
+                               int newS = value;
+                               if (newS < 0)
+                                       newS = 0;
+                               else if (newS > maxScrollX)
+                                       newS = maxScrollX;
+
+                               if (newS == scrollX)
+                                       return;
+
+                               scrollX = value;
+
+                               NotifyValueChanged ("ScrollX", scrollX);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary> Vertical Scrolling Position </summary>
+               [DefaultValue(0)]
+               public virtual int ScrollY {
+                       get { return scrollY; }
+                       set {
+                               if (scrollY == value)
+                                       return;
+
+                               int newS = value;
+                               if (newS < 0)
+                                       newS = 0;
+                               else if (newS > maxScrollY)
+                                       newS = maxScrollY;
+
+                               if (newS == scrollY)
+                                       return;
+
+                               scrollY = value;
+
+                               NotifyValueChanged ("ScrollY", scrollY);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary> Horizontal Scrolling maximum value </summary>
+               [DefaultValue(0)]
+               public virtual int MaxScrollX {
+                       get { return maxScrollX; }
+                       set {
+                               if (maxScrollX == value)
+                                       return;
+
+                               maxScrollX = value;
+
+                               if (scrollX > maxScrollX)
+                                       ScrollX = maxScrollX;
+
+                               NotifyValueChanged ("MaxScrollX", maxScrollX);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary> Vertical Scrolling maximum value </summary>
+               [DefaultValue(0)]
+               public virtual int MaxScrollY {
+                       get { return maxScrollY; }
+                       set {
+                               if (maxScrollY == value)
+                                       return;
+
+                               maxScrollY = value;
+
+                               if (scrollY > maxScrollY)
+                                       ScrollY = maxScrollY;
+
+                               NotifyValueChanged ("MaxScrollY", maxScrollY);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary> Mouse Wheel Scrolling multiplier </summary>
+               [DefaultValue(50)]
+               public virtual int ScrollSpeed {
+                       get { return scrollSpeed; }
+                       set {
+                               if (scrollSpeed == value)
+                                       return;
+
+                               scrollSpeed = value;
+
+                               NotifyValueChanged ("ScrollSpeed", scrollSpeed);
+                       }
+               }
+               #endregion
+
+               public override void SetChild (Widget _child)
+               {
+                       Group g = child as Group;
+                       if (g != null)
+                               g.ChildrenCleared -= onChildListCleared;
+                       
+                       base.SetChild (_child);
+
+                       g = _child as Group;
+                       if (g != null)
+                               g.ChildrenCleared += onChildListCleared;                        
+               }
+               public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
+               {
+                       base.OnChildLayoutChanges (sender, arg);
+                       updateMaxScroll (arg.LayoutType);
+               }
+
+
+               #region GraphicObject Overrides
+               public override Rectangle ScreenCoordinates (Rectangle r)
+               {
+                       return base.ScreenCoordinates (r) - new Point((int)ScrollX,(int)ScrollY);
+               }
+               public override bool PointIsIn (ref Point m)
+               {
+                       if (!base.PointIsIn(ref m))
+                               return false;
+                       if (!Slot.ContainsOrIsEqual (m) || child==null)
+                               return false;
+                       m += new Point (ScrollX, ScrollY);
+                       return true;
+               }
+               public override void RegisterClip (Rectangle clip)
+               {
+                       base.RegisterClip (clip - new Point(ScrollX,ScrollY));
+               }
+               public override void OnLayoutChanges (LayoutingType layoutType)
+               {
+                       base.OnLayoutChanges (layoutType);
+
+                       if (layoutType == LayoutingType.Height)
+                               NotifyValueChanged ("PageHeight", Slot.Height);
+                       else if (layoutType == LayoutingType.Width)
+                               NotifyValueChanged ("PageWidth", Slot.Width);
+                       else
+                               return;
+                       updateMaxScroll(layoutType);
+               }
+               protected override void onDraw (Context gr)
+               {
+                       Rectangle rBack = new Rectangle (Slot.Size);
+
+                       Background.SetAsSource (gr, rBack);
+                       CairoHelpers.CairoRectangle(gr,rBack, CornerRadius);
+                       gr.Fill ();
+
+                       gr.Save ();
+                       if (ClipToClientRect) {
+                               //clip to scrolled client zone
+                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
+                               gr.Clip ();
+                       }
+
+                       gr.Translate (-ScrollX, -ScrollY);
+                       if (child != null)
+                               child.Paint (ref gr);
+                       gr.Restore ();
+               }
+
+               #region Mouse & Keyboard
+               /// <summary> Process scrolling vertically, or if shift is down, vertically </summary>
+               public override void onMouseWheel (object sender, MouseWheelEventArgs e)
+               {
+                       if (IFace.Shift)
+                               ScrollX += e.Delta * ScrollSpeed;
+                       else
+                               ScrollY -= e.Delta * ScrollSpeed;
+                       e.Handled = true;
+                       base.onMouseWheel (sender, e);
+               }
+               /// <summary> Process scrolling with arrow keys, home and end keys. </summary>
+               public override void onKeyDown (object sender, KeyEventArgs e)
+               {
+                       base.onKeyDown (sender, e);
+
+                       if (KeyEventsOverrides)
+                               return;
+
+                       switch (e.Key) {
+                       case Key.Up:
+                               ScrollY--;
+                               break;
+                       case Key.Down:
+                               ScrollY++;
+                               break;
+                       case Key.Left:
+                               ScrollX--;
+                               break;
+                       case Key.Right:
+                               ScrollX++;
+                               break;
+                       case Key.Home:
+                               ScrollX = 0;
+                               ScrollY = 0;
+                               break;
+                       case Key.End:
+                               ScrollX = MaxScrollX;
+                               ScrollY = MaxScrollY;
+                               break;
+                       }
+               }
+               #endregion
+
+               #endregion
+
+               void updateMaxScroll (LayoutingType lt){
+                       if (Child == null) {
+                               MaxScrollX = 0;
+                               MaxScrollY = 0;
+                               return;
+                       }
+
+                       Rectangle cb = ClientRectangle;
+
+                       if (lt == LayoutingType.Height) {
+                               MaxScrollY = child.Slot.Height - cb.Height;
+                               if (child.Slot.Height > 0)
+                                       NotifyValueChanged ("ChildHeightRatio", Slot.Height * Slot.Height / child.Slot.Height);                 
+                       } else if (lt == LayoutingType.Width) {
+                               MaxScrollX = child.Slot.Width - cb.Width;
+                               if (child.Slot.Width > 0)
+                                       NotifyValueChanged ("ChildWidthRatio", Slot.Width * Slot.Width / child.Slot.Width);
+                       }
+               }
+               void onChildListCleared(object sender, EventArgs e){
+                       ScrollY = 0;
+                       ScrollX = 0;
+               }
+
+
+    }
+}
diff --git a/Crow/src/Widgets/ScrollingObject.cs b/Crow/src/Widgets/ScrollingObject.cs
new file mode 100644 (file)
index 0000000..1280489
--- /dev/null
@@ -0,0 +1,190 @@
+//
+// ScrollingObject.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.Xml.Serialization;
+using System.ComponentModel;
+using System.Collections;
+using Crow.Cairo;
+
+
+namespace Crow
+{
+       /// <summary>
+       /// generic class to build scrolling control in both directions
+       /// </summary>
+       [DesignIgnore]
+       public class ScrollingObject : Widget
+       {
+               #region CTOR
+               protected ScrollingObject ():base(){}
+               public ScrollingObject (Interface iface):base(iface){}
+               #endregion
+
+               int scrollX, scrollY, maxScrollX, maxScrollY, mouseWheelSpeed;
+
+               /// <summary>
+               /// if true, key stroke are handled in derrived class
+               /// </summary>
+               protected bool KeyEventsOverrides = false;
+
+               /// <summary> Horizontal Scrolling Position </summary>
+               [DefaultValue(0)]
+               public virtual int ScrollX {
+                       get { return scrollX; }
+                       set {
+                               if (scrollX == value)
+                                       return;
+
+                               int newS = value;
+                               if (newS < 0)
+                                       newS = 0;
+                               else if (newS > maxScrollX)
+                                       newS = maxScrollX;
+
+                               if (newS == scrollX)
+                                       return;
+
+                               scrollX = newS;
+
+                               NotifyValueChanged ("ScrollX", scrollX);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary> Vertical Scrolling Position </summary>
+               [DefaultValue(0)]
+               public virtual int ScrollY {
+                       get { return scrollY; }
+                       set {
+                               if (scrollY == value)
+                                       return;
+
+                               int newS = value;
+                               if (newS < 0)
+                                       newS = 0;
+                               else if (newS > maxScrollY)
+                                       newS = maxScrollY;
+
+                               if (newS == scrollY)
+                                       return;
+
+                               scrollY = newS;
+
+                               NotifyValueChanged ("ScrollY", scrollY);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary> Horizontal Scrolling maximum value </summary>
+               [DefaultValue(0)]
+               public virtual int MaxScrollX {
+                       get { return maxScrollX; }
+                       set {
+                               if (maxScrollX == value)
+                                       return;
+
+                               maxScrollX = value;
+
+                               if (scrollX > maxScrollX)
+                                       ScrollX = maxScrollX;
+                               
+                               NotifyValueChanged ("MaxScrollX", maxScrollX);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary> Vertical Scrolling maximum value </summary>
+               [DefaultValue(0)]
+               public virtual int MaxScrollY {
+                       get { return maxScrollY; }
+                       set {
+                               if (maxScrollY == value)
+                                       return;
+
+                               maxScrollY = value;
+
+                               if (scrollY > maxScrollY)
+                                       ScrollY = maxScrollY;
+
+                               NotifyValueChanged ("MaxScrollY", maxScrollY);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary> Mouse Wheel Scrolling multiplier </summary>
+               [DefaultValue(1)]
+               public virtual int MouseWheelSpeed {
+                       get { return mouseWheelSpeed; }
+                       set {
+                               if (mouseWheelSpeed == value)
+                                       return;
+                               
+                               mouseWheelSpeed = value;
+
+                               NotifyValueChanged ("MouseWheelSpeed", mouseWheelSpeed);
+                       }
+               }
+
+               /// <summary> Process scrolling vertically, or if shift is down, vertically </summary>
+               public override void onMouseWheel (object sender, MouseWheelEventArgs e)
+               {
+                       base.onMouseWheel (sender, e);
+                       if (IFace.Shift)
+                               ScrollX += e.Delta * MouseWheelSpeed;
+                       else
+                               ScrollY -= e.Delta * MouseWheelSpeed;
+               }
+               /// <summary> Process scrolling with arrow keys, home and end keys. </summary>
+               public override void onKeyDown (object sender, KeyEventArgs e)
+               {
+                       base.onKeyDown (sender, e);
+
+                       if (KeyEventsOverrides)
+                               return;
+
+                       switch (e.Key) {
+                       case Key.Up:
+                               ScrollY--;
+                               break;
+                       case Key.Down:
+                               ScrollY++;
+                               break;
+                       case Key.Left:
+                               ScrollX--;
+                               break;
+                       case Key.Right:
+                               ScrollX++;
+                               break;
+                       case Key.Home:
+                               ScrollX = 0;
+                               ScrollY = 0;
+                               break;
+                       case Key.End:
+                               ScrollX = MaxScrollX;
+                               ScrollY = MaxScrollY;
+                               break;
+                       }
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/Shape.cs b/Crow/src/Widgets/Shape.cs
new file mode 100644 (file)
index 0000000..952c373
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Text;
+using Crow.Cairo;
+
+namespace Crow
+{
+       public class PathParser : StringReader
+       {
+               public PathParser (string str) : base (str) {}
+
+               double readDouble () {
+                       StringBuilder tmp = new StringBuilder();
+
+                       while (Peek () >= 0) {                          
+                               char c = (char)Read();
+                               if (c.IsWhiteSpaceOrNewLine()) {
+                                       if (tmp.Length == 0)
+                                               continue;
+                                       else
+                                               break;
+                               } else if (c == ',')
+                                       break;                          
+                               tmp.Append (c);
+                       }
+                       return double.Parse (tmp.ToString ());
+               }
+               public void Draw (Context gr) {
+                       while (Peek () >= 0) {
+                               char c = (char)Read ();
+                               if (c.IsWhiteSpaceOrNewLine ())
+                                       continue;
+                               switch (c) {
+                               case 'M':
+                                       gr.MoveTo (readDouble (), readDouble ());
+                                       break;
+                               case 'm':
+                                       gr.RelMoveTo (readDouble (), readDouble ());
+                                       break;
+                               case 'L':
+                                       gr.LineTo (readDouble (), readDouble ());
+                                       break;
+                               case 'l':
+                                       gr.RelLineTo (readDouble (), readDouble ());
+                                       break;
+                               case 'C':
+                                       gr.CurveTo (readDouble (), readDouble (), readDouble (), readDouble (), readDouble (), readDouble ());
+                                       break;
+                               case 'c':
+                                       gr.RelCurveTo (readDouble (), readDouble (), readDouble (), readDouble (), readDouble (), readDouble ());
+                                       break;
+                               case 'Z':
+                                       gr.ClosePath ();
+                                       break;
+                               case 'F':
+                                       gr.Fill ();
+                                       break;
+                               case 'G':
+                                       gr.Stroke ();
+                                       break;
+                               default:
+                                       throw new Exception ("Invalid character in path string of Shape control");
+                               }
+                       }                       
+               }
+       }
+       public class Shape : Widget
+       {
+               #region CTOR
+               protected Shape () : base() {}
+               public Shape (Interface iface) : base (iface) {}
+               #endregion
+
+               string path;
+               double strokeWidth;
+        Size size;
+
+               public string Path {
+                       get { return path; }
+                       set {
+                               if (path == value)
+                                       return;
+                               path = value;
+                               contentSize = default (Size);
+                               NotifyValueChanged ("Path", path);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               [DefaultValue(1.0)]
+               public double StokeWidth {
+                       get { return strokeWidth; }
+                       set {
+                               if (strokeWidth == value)
+                                       return;
+                               strokeWidth = value;
+                               contentSize = default (Size);
+                               NotifyValueChanged ("StrokeWidth", strokeWidth);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+        [DefaultValue("0,0")]
+        public Size Size
+        {
+            get { return size; }
+            set
+            {
+                if (size == value)
+                    return;
+                size = value;
+                contentSize = default(Size);
+                NotifyValueChanged("Size", size);
+                RegisterForLayouting(LayoutingType.Sizing);
+            }
+        }
+        protected override void onDraw(Context gr)
+        {
+
+            if (string.IsNullOrEmpty(path))
+                return;
+
+            gr.Save();
+
+            Rectangle r = ClientRectangle;
+
+
+            double sx = (double)r.Width / (double)(contentSize.Width == 0? size.Width : contentSize.Width);
+            double sy = (double)r.Height / (double)(contentSize.Height == 0 ? size.Height : contentSize.Height);            
+
+            gr.Translate(r.Left, r.Top);
+            gr.Scale (sx,sy);
+
+                       using (PathParser parser = new PathParser (path))
+                               parser.Draw (gr);
+                               
+                       Background.SetAsSource (gr, r);
+                       gr.FillPreserve ();
+                       gr.LineWidth = strokeWidth;
+                       Foreground.SetAsSource (gr, r);
+                       gr.Stroke ();
+            gr.Restore();
+               }
+
+
+               protected override int measureRawSize (LayoutingType lt)
+               {
+                       if ((lt == LayoutingType.Width && contentSize.Width == 0) || (lt == LayoutingType.Height && contentSize.Height == 0)) {
+                if (size != default(Size))
+                    contentSize = size;
+                else
+                {
+                    using (Surface drawing = new ImageSurface(Format.A1, 1, 1))
+                    {
+                        using (Context ctx = new Context(drawing))
+                        {
+                                                       using (PathParser parser = new PathParser (path))
+                                                               parser.Draw (ctx);                                                              
+                            Rectangle r = ctx.StrokeExtents();
+                            contentSize = new Size(r.Right, r.Bottom);
+                        }
+                    }
+                }
+                       }
+                       return lt == LayoutingType.Width ?
+                               contentSize.Width + 2 * Margin: contentSize.Height + 2 * Margin;
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/Slider.cs b/Crow/src/Widgets/Slider.cs
new file mode 100644 (file)
index 0000000..e4942b2
--- /dev/null
@@ -0,0 +1,258 @@
+//
+// Slider.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 Crow.Cairo;
+using System.Xml.Serialization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace Crow
+{
+       /// <summary>
+       /// templated numeric control to select a value
+       /// by slidding a cursor
+       /// </summary>
+       public class Slider : NumericControl
+    {
+               #region CTOR
+               protected Slider() : base(){}
+               public Slider(Interface iface) : base(iface)
+               {}
+//             public Slider(double minimum, double maximum, double step)
+//                     : base(minimum,maximum,step)
+//             {
+//             }
+               #endregion
+
+               #region implemented abstract members of TemplatedControl
+
+               protected override void loadTemplate (Widget template = null)
+               {
+                       
+               }
+
+               #endregion
+
+               #region private fields
+        Rectangle cursor;
+               int _cursorSize;
+               Fill _cursorColor;
+               Orientation _orientation;
+               bool holdCursor = false;
+               #endregion
+
+               protected double unity;
+
+               #region Public properties
+               [DefaultValue("vgradient|0:White|0,1:LightGrey|0,9:LightGrey|1:DimGrey")]
+               public virtual Fill CursorColor {
+                       get { return _cursorColor; }
+                       set {
+                               if (_cursorColor == value)
+                                       return;
+                               _cursorColor = value;
+                               RegisterForRedraw ();
+                               NotifyValueChanged ("CursorColor", _cursorColor);
+                       }
+               }
+               [DefaultValue(20)]
+               public virtual int CursorSize {
+                       get { return _cursorSize; }
+                       set {
+                               if (_cursorSize == value || value < 8)
+                                       return;
+                               _cursorSize = value;
+                               RegisterForGraphicUpdate ();
+                               NotifyValueChanged ("CursorSize", _cursorSize);
+                       }
+               }
+               [DefaultValue(Orientation.Horizontal)]
+               public virtual Orientation Orientation
+               {
+                       get { return _orientation; }
+                       set { 
+                               if (_orientation == value)
+                                       return;
+                               _orientation = value; 
+
+                               RegisterForLayouting (LayoutingType.All);
+                               NotifyValueChanged ("Orientation", _orientation);
+                       }
+               }
+               #endregion
+
+               //[DefaultValue(10.0)]
+               //public override double Maximum {
+               //      get { return base.Maximum; }
+               //      set {                           
+               //              if (value == base.Maximum)
+               //                      return;
+               //              base.Maximum = value;
+               //              LargeIncrement = base.Maximum / 10.0;
+               //              SmallIncrement = LargeIncrement / 5.0;
+               //      }
+               //}
+
+               #region GraphicObject Overrides
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       if (Maximum <= 0)
+                               return;
+
+                       computeCursorPosition ();
+
+                       Rectangle r = ClientRectangle;
+                       PointD pStart;
+                       PointD pEnd;
+                       if (_orientation == Orientation.Horizontal) {
+                               pStart = r.TopLeft + new Point (_cursorSize / 2, r.Height / 2);
+                               pEnd = r.TopRight + new Point (-_cursorSize / 2, r.Height / 2);
+                               pStart.Y += 0.5;
+                               pEnd.Y += 0.5;
+                       } else {
+                               pStart = r.TopLeft + new Point (r.Width / 2, _cursorSize / 2);
+                               pEnd = r.BottomLeft + new Point (r.Width / 2,- _cursorSize / 2);
+                               pStart.X += 0.5;
+                               pEnd.X += 0.5;
+
+                       }
+
+            Background.SetAsSource(gr, r);
+            gr.Rectangle (r);
+            gr.Fill ();
+
+                       DrawGraduations (gr, pStart,pEnd);
+
+                       DrawCursor (gr, cursor);
+               }
+               #endregion
+
+               protected virtual void DrawGraduations(Context gr, PointD pStart, PointD pEnd)
+               {
+                       Foreground.SetAsSource (gr);
+
+                       gr.LineWidth = 1;
+                       gr.MoveTo(pStart);
+                       gr.LineTo(pEnd);
+
+                       gr.Stroke();
+
+               }
+               protected virtual void DrawCursor(Context gr, Rectangle _cursor)
+               {
+                       CairoHelpers.CairoRectangle (gr, _cursor, CornerRadius);
+            Foreground.SetAsSource(gr, _cursor);
+            gr.StrokePreserve();
+            CursorColor.SetAsSource(gr, _cursor);
+            gr.Fill();
+               }
+
+        void computeCursorPosition()
+        {            
+            Rectangle r = ClientRectangle;
+                       PointD p1; 
+
+                       if (_orientation == Orientation.Horizontal) {
+                               cursor = new Rectangle (new Size (_cursorSize, (int)(r.Height)));
+                               p1 = r.TopLeft + new Point (_cursorSize / 2, r.Height / 2);
+                               unity = (double)(r.Width - _cursorSize) / (Maximum - Minimum);
+                               cursor.TopLeft = new Point (r.Left + (int)((Value - Minimum) * unity),
+                                       (int)(p1.Y - cursor.Height / 2));
+                       } else {
+                               cursor = new Rectangle (new Size ((int)(r.Width), _cursorSize));
+                               p1 = r.TopLeft + new Point (r.Width / 2, _cursorSize / 2);
+                               unity = (double)(r.Height - _cursorSize) / (Maximum - Minimum);
+                               cursor.TopLeft = new Point ((int)(p1.X - r.Width / 2),
+                                       r.Top + (int)((Value - Minimum) * unity));                              
+                       }
+                       //cursor.Inflate (-1);
+        }
+               Point mouseDownInit;
+               double mouseDownInitValue;
+
+               #region mouse handling
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseDown (sender, e);
+                       mouseDownInit = ScreenPointToLocal (e.Position);
+                       mouseDownInitValue = Value;
+                       Rectangle cursInScreenCoord = ScreenCoordinates (cursor + Slot.Position);
+                       if (cursInScreenCoord.ContainsOrIsEqual (e.Position)){
+//                             Rectangle r = ClientRectangle;
+//                             if (r.Width - _cursorSize > 0) {
+//                                     double unit = (Maximum - Minimum) / (double)(r.Width - _cursorSize);
+//                                     mouseDownInit += new Point ((int)(Value / unit), (int)(Value / unit));
+//                             }
+                               holdCursor = true;
+                       }else if (_orientation == Orientation.Horizontal) {
+                               if (e.Position.X < cursInScreenCoord.Left)
+                                       Value -= LargeIncrement;
+                               else
+                                       Value += LargeIncrement;
+                       } else {
+                               if (e.Position.Y < cursInScreenCoord.Top)
+                                       Value -= LargeIncrement;
+                               else
+                                       Value += LargeIncrement;
+                       }
+               }
+               public override void onMouseUp (object sender,MouseButtonEventArgs e)
+               {
+                       base.onMouseUp (sender, e);
+
+                       holdCursor = false;
+               }
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       if (holdCursor) {                               
+                               Point m = ScreenPointToLocal (e.Position) - mouseDownInit;
+                               Rectangle r = ClientRectangle;
+
+                               if (_orientation == Orientation.Horizontal) {
+                                       if (r.Width - _cursorSize == 0)
+                                               return;                                 
+                                       double unit = (Maximum - Minimum) / (double)(r.Width - _cursorSize);
+                                       double tmp = mouseDownInitValue + (double)m.X * unit;
+                                       tmp -= tmp % SmallIncrement;
+                                       Value = tmp;
+                               } else {
+                                       if (r.Height - _cursorSize == 0)
+                                               return;                                 
+                                       double unit = (Maximum - Minimum) / (double)(r.Height - _cursorSize);
+                                       double tmp = mouseDownInitValue + (double)m.Y * unit;
+                                       tmp -= tmp % SmallIncrement;
+                                       Value = tmp;
+                               }
+                       }
+                       
+                       base.onMouseMove (sender, e);
+               }
+               #endregion
+    }
+}
diff --git a/Crow/src/Widgets/Spinner.cs b/Crow/src/Widgets/Spinner.cs
new file mode 100644 (file)
index 0000000..8a3bcd6
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+namespace Crow
+{
+       /// <summary>
+       /// templated control for selecting a numeric value by clicking on
+       /// up and down buttons
+       /// </summary>
+       public class Spinner : NumericControl
+       {
+               #region CTOR
+               protected Spinner() : base(){}
+               public Spinner (Interface iface) : base(iface)
+               {
+               }
+               #endregion
+
+               void onUp (object sender, MouseButtonEventArgs e)
+               {
+                       Value += this.SmallIncrement;
+               }
+               void onDown (object sender, MouseButtonEventArgs e)
+               {
+                       Value -= this.SmallIncrement;
+               }
+
+       }
+}
+
diff --git a/Crow/src/Widgets/Splitter.cs b/Crow/src/Widgets/Splitter.cs
new file mode 100644 (file)
index 0000000..e3f2161
--- /dev/null
@@ -0,0 +1,232 @@
+//
+// Splitter.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.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       /// <summary>
+       /// control to add between children of a Stack to allow them to be resized
+       /// with the pointer
+       /// </summary>
+       public class Splitter : Widget
+       {
+               #region CTOR
+               protected Splitter() : base(){}
+               public Splitter (Interface iface) : base(iface){}
+               #endregion
+
+               int thickness;
+
+               [DefaultValue(1)]
+               public virtual int Thickness {
+                       get { return thickness; }
+                       set {
+                               if (thickness == value)
+                                       return;
+                               thickness = value; 
+                               NotifyValueChanged ("Thickness", thickness);
+                               RegisterForLayouting (LayoutingType.Sizing);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+
+               Unit u1, u2;
+               int init1 = -1, init2 = -1, delta = 0, min1, min2, max1 , max2;
+               Widget go1 = null, go2 = null;
+
+               void initSplit(Measure m1, int size1, Measure m2, int size2){
+                       if (m1 != Measure.Stretched) {
+                               init1 = size1;
+                               u1 = m1.Units;
+                       }
+                       if (m2 != Measure.Stretched) {
+                               init2 = size2;
+                               u2 = m2.Units;
+                       }
+               }
+               void convertSizeInPix(Widget g1){
+
+               }
+
+               #region GraphicObject override
+               public override ILayoutable Parent {
+                       get { return base.Parent; }
+                       set {
+                               if (value != null) {                    
+                                       GenericStack gs = value as GenericStack;
+                                       if (gs == null)
+                                               throw new Exception ("Splitter may only be chil of stack");
+                                       
+                               }
+                               base.Parent = value;
+                       }
+               }
+               public override void onMouseEnter (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseEnter (sender, e);
+                       if ((Parent as GenericStack).Orientation == Orientation.Horizontal)
+                               IFace.MouseCursor = MouseCursor.H;
+                       else
+                               IFace.MouseCursor = MouseCursor.V;
+               }
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseDown (sender, e);
+                       go1 = go2 = null;
+                       init1 = init2 = -1;
+                       delta = 0;
+
+                       GenericStack gs = Parent as GenericStack;
+                       int ptrSplit = gs.Children.IndexOf (this);
+                       if (ptrSplit == 0 || ptrSplit == gs.Children.Count - 1)
+                               return;
+
+                       go1 = gs.Children [ptrSplit - 1];
+                       go2 = gs.Children [ptrSplit + 1];
+
+                       if (gs.Orientation == Orientation.Horizontal) {
+                               initSplit (go1.Width, go1.Slot.Width, go2.Width, go2.Slot.Width);
+                               min1 = go1.MinimumSize.Width;
+                               min2 = go2.MinimumSize.Width;
+                               max1 = go1.MaximumSize.Width;
+                               max2 = go2.MaximumSize.Width;
+                               if (init1 >= 0)
+                                       go1.Width = init1;
+                               if (init2 >= 0)
+                                       go2.Width = init2;
+                       } else {
+                               initSplit (go1.Height, go1.Slot.Height, go2.Height, go2.Slot.Height);
+                               min1 = go1.MinimumSize.Height;
+                               min2 = go2.MinimumSize.Height;
+                               max1 = go1.MaximumSize.Height;
+                               max2 = go2.MaximumSize.Height;
+                               if (init1 >= 0)
+                                       go1.Height = init1;
+                               if (init2 >= 0)
+                                       go2.Height = init2;
+                       }
+               }
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseMove (sender, e);
+
+                       if (!IsActive || go1 == null || go2 == null)
+                               return;
+
+                       GenericStack gs = Parent as GenericStack;
+                       int newDelta = delta, size1 = init1 , size2 = init2;
+                       if (gs.Orientation == Orientation.Horizontal) {
+                               newDelta -= e.XDelta;
+                               if (size1 < 0)
+                                       size1 = go1.Slot.Width + delta;
+                               if (size2 < 0)
+                                       size2 = go2.Slot.Width - delta;
+                       } else {
+                               newDelta -= e.YDelta;
+                               if (size1 < 0)
+                                       size1 = go1.Slot.Height + delta;
+                               if (size2 < 0)
+                                       size2 = go2.Slot.Height - delta;
+                       }
+
+                       if (size1 - newDelta < min1 || (max1 > 0 && size1 - newDelta > max1) ||
+                               size2 + newDelta < min2 || (max2 > 0 && size2 + newDelta > max2))
+                               return;
+
+                       delta = newDelta;
+
+                       if (gs.Orientation == Orientation.Horizontal) {
+                               if (init1 >= 0)
+                                       go1.Width = init1 - delta;
+                               if (init2 >= 0)
+                                       go2.Width = init2 + delta;
+                       } else {
+                               if (init1 >= 0)
+                                       go1.Height = init1 - delta;
+                               if (init2 >= 0)
+                                       go2.Height = init2 + delta;
+                       }
+               }
+               public override void onMouseUp (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseUp (sender, e);
+
+                       GenericStack gs = Parent as GenericStack;
+
+                       if (init1 >= 0 && u1 == Unit.Percent) {
+                               if (gs.Orientation == Orientation.Horizontal)
+                                       go1.Width = new Measure ((int)Math.Ceiling (
+                                               go1.Width.Value * 100.0 / (double)gs.Slot.Width), Unit.Percent);
+                               else
+                                       go1.Height = new Measure ((int)Math.Ceiling (
+                                               go1.Height.Value * 100.0 / (double)gs.Slot.Height), Unit.Percent);
+                       }
+                       if (init2 >= 0 && u2 == Unit.Percent) {
+                               if (gs.Orientation == Orientation.Horizontal)
+                                       go2.Width = new Measure ((int)Math.Floor (
+                                               go2.Width.Value * 100.0 / (double)gs.Slot.Width), Unit.Percent);
+                               else
+                                       go2.Height = new Measure ((int)Math.Floor (
+                                               go2.Height.Value * 100.0 / (double)gs.Slot.Height), Unit.Percent);
+                       }
+               }
+               public override bool UpdateLayout (LayoutingType layoutType)
+               {
+                       GenericStack gs = Parent as GenericStack;
+                       if (layoutType == LayoutingType.Width){
+                               if (gs.Orientation == Orientation.Horizontal)
+                                       Width = thickness;
+                               else
+                                       Width = Measure.Stretched;
+                       } else if (layoutType == LayoutingType.Height){
+                               if (gs.Orientation == Orientation.Vertical)
+                                       Height = thickness;
+                               else
+                                       Height = Measure.Stretched;
+                       }
+                       return base.UpdateLayout (layoutType);
+               }
+               public override bool PointIsIn (ref Point m)
+               {
+                       if (!(Visible & IsEnabled)||IsDragged)
+                               return false;
+                       if (!Parent.PointIsIn(ref m))
+                               return false;
+                       m -= (Parent.getSlot().Position + Parent.ClientRectangle.Position) ;
+                       Rectangle r = Slot;
+                       if (Width == Measure.Stretched)
+                               r.Inflate (0, 5);
+                       else
+                               r.Inflate (5, 0);
+                       return r.ContainsOrIsEqual (m); 
+               }
+               #endregion
+       }
+}
+
diff --git a/Crow/src/Widgets/TabItem.cs b/Crow/src/Widgets/TabItem.cs
new file mode 100644 (file)
index 0000000..7c20a33
--- /dev/null
@@ -0,0 +1,336 @@
+//
+// TabItem.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.Xml.Serialization;
+using System.ComponentModel;
+using System.Diagnostics;
+using Crow.Cairo;
+using System.Linq;
+
+namespace Crow
+{
+       public class TabItem : TemplatedContainer
+       {
+               #region CTOR
+               protected TabItem() : base(){}
+               public TabItem (Interface iface) : base(iface){}
+               #endregion
+
+               public event EventHandler QueryClose;
+
+               internal TabView tview = null;
+
+               #region Private fields
+               Widget titleWidget;
+               int tabOffset;
+               bool isSelected;
+               //Measure tabThickness;
+               Fill selectedBackground = Color.Transparent;
+               #endregion
+
+               #region TemplatedControl overrides
+               public override Widget Content {
+                       get {
+                               return _contentContainer == null ? null : _contentContainer.Child;
+                       }
+                       set {
+                               if (Content != null) {
+                                       Content.LogicalParent = null;
+                                       _contentContainer.SetChild (null);
+                               }
+                               _contentContainer.SetChild(value);
+                               if (value != null)
+                                       value.LogicalParent = this;
+                       }
+               }
+               protected override void loadTemplate(Widget template = null)
+               {
+                       base.loadTemplate (template);
+
+                       titleWidget = this.child.FindByName ("TabTitle");
+               }
+               internal Widget TabTitle { get { return titleWidget; }}
+               #endregion
+
+               /// <summary>
+               /// order of redrawing, items can't be reordered in TemplatedGroup due to data linked, so we need another index
+               /// instead of children list order
+               /// </summary>
+               public int viewIndex = 0;
+               public virtual int ViewIndex {
+                       get { return viewIndex; }
+                       set {
+                               if (viewIndex == value)
+                                       return;
+                               viewIndex = value;
+                               NotifyValueChanged ("ViewIndex", viewIndex);
+                       }
+               }
+                       
+               [DefaultValue(0)]
+               public int TabOffset {
+                       get { return tabOffset; }
+                       set {
+                               if (tabOffset == value)
+                                       return;
+                               tabOffset = value;
+                               NotifyValueChanged ("TabOffset", tabOffset);
+
+                               RegisterForLayouting (LayoutingType.X);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               public Measure TabHeight {
+                       get { return tview == null ? Measure.Fit : tview.TabHeight; }
+               }
+               public Measure TabWidth {
+                       get { return tview == null ? Measure.Fit : tview.TabWidth; }
+               }
+               [DefaultValue(false)]
+               public virtual bool IsSelected {
+                       get { return isSelected; }
+                       set {
+                               if (isSelected == value)
+                                       return;
+
+                               if (tview != null)
+                                       tview.SelectedTab = tview.Children.IndexOf(this);
+                               
+                               isSelected = value;
+                               NotifyValueChanged ("IsSelected", isSelected);
+                               RegisterForRedraw ();
+                       }
+               }
+
+               /// <summary>
+               /// background fill of the control, maybe solid color, gradient, image, or svg
+               /// </summary>
+               [DesignCategory ("Appearance")][DefaultValue("DimGrey")]
+               public virtual Fill SelectedBackground {
+                       get { return selectedBackground; }
+                       set {
+                               if (selectedBackground == value)
+                                       return;                         
+                               if (value == null)
+                                       return;
+                               selectedBackground = value;
+                               NotifyValueChanged ("SelectedBackground", selectedBackground);
+                               RegisterForRedraw ();
+                       }
+               }
+               protected override void onDraw (Context gr)
+               {
+                       gr.Save ();
+
+                       TabView tv = Parent as TabView;
+
+                       Rectangle r = TabTitle.Slot;
+                       r.Width = TabWidth;
+
+                       gr.MoveTo (0.5, r.Bottom-0.5);
+                       gr.LineTo (r.Left - tv.LeftSlope, r.Bottom-0.5);
+                       gr.CurveTo (
+                               r.Left - tv.LeftSlope / 2, r.Bottom-0.5,
+                               r.Left - tv.LeftSlope / 2, 0.5,
+                               r.Left, 0.5);
+                       gr.LineTo (r.Right, 0.5);
+                       gr.CurveTo (
+                               r.Right + tv.RightSlope / 2, 0.5,
+                               r.Right + tv.RightSlope / 2, r.Bottom-0.5,
+                               r.Right + tv.RightSlope, r.Bottom-0.5);
+                       gr.LineTo (Slot.Width-0.5, r.Bottom-0.5);
+
+
+                       gr.LineTo (Slot.Width-0.5, Slot.Height-0.5);
+                       gr.LineTo (0.5, Slot.Height-0.5);
+                       gr.ClosePath ();
+                       gr.LineWidth = 1;
+                       Foreground.SetAsSource (gr);
+                       gr.StrokePreserve ();
+                       gr.ClipPreserve ();
+
+                       if (IsSelected)
+                               SelectedBackground.SetAsSource (gr, ClientRectangle);
+                       else
+                               Background.SetAsSource (gr, ClientRectangle);
+
+                       gr.Fill ();
+
+                       base.onDraw (gr);
+
+                       gr.Restore ();
+               }
+
+               Point dragStartPoint;
+               int dragThreshold = 16;
+               int dis = 128;
+               internal TabView savedParent = null;
+
+
+               void makeFloating (TabView tv) {                        
+                       lock (IFace.UpdateMutex) {                              
+                               ImageSurface di = new ImageSurface (Format.Argb32, dis, dis);
+                               IFace.DragImageHeight = dis;
+                               IFace.DragImageWidth = dis;
+                               using (Context ctx = new Context (di)) {
+                                       double div = Math.Max (LastPaintedSlot.Width, LastPaintedSlot.Height);
+                                       double s = (double)dis / div;
+                                       ctx.Scale (s, s);
+                                       if (bmp == null)
+                                               this.onDraw (ctx);
+                                       else {
+                                               if (LastPaintedSlot.Width>LastPaintedSlot.Height)
+                                                       ctx.SetSourceSurface (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2);
+                                               else
+                                                       ctx.SetSourceSurface (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0);
+
+                                               ctx.Paint ();
+                                       }
+                               }
+                               IFace.DragImage = di;
+                       }
+                       tv.RemoveChild (this);
+                       savedParent = tv;
+               }
+
+               public override ILayoutable Parent {
+                       get {
+                               return base.Parent;
+                       }
+                       set {
+                               base.Parent = value;
+                               if (value != null) {
+                                       dragStartPoint = IFace.Mouse.Position;
+                                       savedParent = value as TabView;
+                               }
+                       }
+               }
+               protected override void onStartDrag (object sender, DragDropEventArgs e)
+               {
+                       base.onStartDrag (sender, e);
+
+                       dragStartPoint = IFace.Mouse.Position;
+               }
+               protected override void onEndDrag (object sender, DragDropEventArgs e)
+               {
+                       base.onEndDrag (sender, e);
+
+                       if (Parent != null)
+                               return;
+
+                       savedParent.AddChild (this);
+
+                       IFace.ClearDragImage ();
+               }
+               protected override void onDrop (object sender, DragDropEventArgs e)
+               {
+                       base.onDrop (sender, e);
+                       if (Parent != null)
+                               return;
+                       TabView tv = e.DropTarget as TabView;
+                       if (tv == null)
+                               return;
+
+                       IFace.ClearDragImage ();
+
+                       tv.AddChild (this);
+               }
+               #region Mouse Handling
+               public override bool PointIsIn (ref Point m)
+               {
+                       if (!base.PointIsIn (ref m))
+                               return false;
+                       if (tview == null)//double check this, just added to prevent exception
+                               return false;
+                       if (m.Y < tview.TabHeight)
+                               return TabTitle.Slot.ContainsOrIsEqual (m);
+                       else
+                               return this.isSelected;
+               }
+               public override void onMouseUp (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseUp (sender, e);
+                       tview?.UpdateLayout (LayoutingType.ArrangeChildren);
+               }
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseMove (sender, e);
+
+                       if (Parent == null)
+                               return;
+                       
+                       if (!IsDragged)
+                               return;
+
+                       TabView tv = Parent as TabView;
+                       if (Math.Abs (e.Position.Y - dragStartPoint.Y) > dragThreshold ||
+                               Math.Abs (e.Position.X - dragStartPoint.X) > dragThreshold) {
+                               makeFloating (tv);
+                               return;
+                       }
+
+                       Rectangle cb = ClientRectangle;
+
+                       int tmp = TabOffset + e.XDelta;
+                       if (tmp < tview.LeftSlope) {                            
+                               TabOffset = tview.LeftSlope;
+                       } else if (tmp > cb.Width - tv.RightSlope - tv.TabWidth) {
+                               TabOffset = cb.Width - tv.RightSlope - tv.TabWidth;
+                       }else{
+                               dragStartPoint.X = e.Position.X;
+                               TabItem[] tabItms = tv.Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
+                               if (ViewIndex > 0 && e.XDelta < 0) {
+                                       TabItem previous = tabItms [ViewIndex - 1];
+                                       if (tmp < previous.TabOffset + tview.TabWidth / 2) {
+                                               previous.ViewIndex = ViewIndex;
+                                               ViewIndex--;
+                                               tv.UpdateLayout (LayoutingType.ArrangeChildren);
+                                       }
+
+                               }else if (ViewIndex < tabItms.Length - 1 && e.XDelta > 0) {
+                                       TabItem next = tabItms [ViewIndex + 1];
+                                       if (tmp > next.TabOffset - tview.TabWidth / 2){
+                                               next.ViewIndex = ViewIndex;
+                                               ViewIndex++;
+                                               tv.UpdateLayout (LayoutingType.ArrangeChildren);
+                                       }
+                               }
+                               TabOffset = tmp;
+                       }
+               }
+               public void butCloseTabClick (object sender, MouseButtonEventArgs e){                   
+                       QueryClose.Raise (this, null);
+                       //if tab is used as a templated item root in a templatedGroup, local datasource
+                       //is not null, in this case, removing the data entries will delete automatically the item
+                       if (localDataSourceIsNull)
+                               (Parent as TabView)?.DeleteChild (this);
+               }
+               #endregion
+
+       }
+}
+
diff --git a/Crow/src/Widgets/TabView.cs b/Crow/src/Widgets/TabView.cs
new file mode 100644 (file)
index 0000000..423b8ab
--- /dev/null
@@ -0,0 +1,337 @@
+//
+// TabView.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.Xml.Serialization;
+using System.ComponentModel;
+using Crow.Cairo;
+using System.Diagnostics;
+using System.Linq;
+
+namespace Crow
+{      
+       public class TabView : Group
+       {
+               #region CTOR
+               public TabView() : base(){}
+               public TabView (Interface iface) : base(iface){}
+               #endregion
+
+               #region Private fields
+               int adjustedTab = -1;
+               int leftSlope;
+               int rightSlope;
+               Measure tabHeight, tabWidth;
+               Orientation _orientation;
+               int selectedTab;
+               #endregion
+
+               #region public properties
+               [DefaultValue(Orientation.Horizontal)]
+               public virtual Orientation Orientation
+               {
+                       get { return _orientation; }
+                       set {
+                               if (_orientation == value)
+                                       return;
+                               _orientation = value;
+                               NotifyValueChanged ("Orientation", _orientation);
+                               if (_orientation == Orientation.Horizontal)
+                                       NotifyValueChanged ("TabOrientation", Orientation.Vertical);
+                               else
+                                       NotifyValueChanged ("TabOrientation", Orientation.Horizontal);                          
+                               this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+                       }
+               }
+               [DefaultValue(16)]
+               public int LeftSlope
+               {
+                       get { return leftSlope; }
+                       set {
+                               if (leftSlope == value)
+                                       return;
+                               leftSlope = value;
+                               NotifyValueChanged ("leftSlope", leftSlope);
+                               //tabSizeHasChanged = true;
+                               //RegisterForLayouting (LayoutingType.ArrangeChildren);
+                       }
+               }
+               //bool tabSizeHasChanged = false;
+               [DefaultValue(16)]
+               public int RightSlope
+               {
+                       get { return rightSlope; }
+                       set {
+                               if (rightSlope == value)
+                                       return;
+                               rightSlope = value;
+                               NotifyValueChanged ("RightSlope", rightSlope);
+                               //tabSizeHasChanged = true;
+                               //RegisterForLayouting (LayoutingType.ArrangeChildren);
+                       }
+               }
+               [DefaultValue("18")]
+               public Measure TabHeight {
+                       get { return tabHeight; }
+                       set {
+                               if (tabHeight == value)
+                                       return;
+                               tabHeight = value;
+                               NotifyValueChanged ("TabHeight", tabHeight);
+//                             childrenRWLock.EnterReadLock ();
+//                             foreach (GraphicObject ti in Children) {
+//                                     ti.NotifyValueChanged ("TabHeight", tabHeight);
+//                             }
+//                             childrenRWLock.ExitReadLock ();
+                               RegisterForLayouting (LayoutingType.ArrangeChildren);
+                       }
+               }
+               [DefaultValue("120")]
+               public Measure TabWidth {
+                       get { return adjustedTab > 0 ? (Measure)adjustedTab : tabWidth; }
+                       set {
+                               if (tabWidth == value)
+                                       return;
+                               tabWidth = value;
+                               NotifyValueChanged ("TabWidth", TabWidth);
+//
+//                             childrenRWLock.EnterReadLock ();
+//                             foreach (GraphicObject ti in Children) { 
+//                                     ti.NotifyValueChanged ("TabWidth", tabWidth);
+//                             }
+//                             childrenRWLock.ExitReadLock ();
+                               RegisterForLayouting (LayoutingType.ArrangeChildren);
+                       }
+               }
+
+               public virtual int SelectedTab {
+                       get { return selectedTab; }
+                       set {
+                               if (value == selectedTab)
+                                       return;
+
+                               if (selectedTab < Children.Count && selectedTab >= 0)
+                                       (Children [selectedTab] as TabItem).IsSelected = false;
+
+                               selectedTab = value;
+
+                               if (selectedTab < Children.Count && selectedTab >= 0)
+                                       (Children [selectedTab] as TabItem).IsSelected = true;
+
+                               NotifyValueChanged ("SelectedTab", selectedTab);
+                               RegisterForRedraw ();
+                       }
+               }
+               #endregion
+
+               public override void AddChild (Widget child)
+               {
+                       TabItem ti = child as TabItem;
+                       if (ti == null)
+                               throw new Exception ("TabView control accept only TabItem as child.");
+
+                       ti.MouseDown += Ti_MouseDown;
+                       ti.TabTitle.LayoutChanged += Ti_TabTitle_LayoutChanged;
+                       ti.tview = this;
+
+                       base.AddChild (child);
+
+                       SelectedTab = ti.ViewIndex = Children.Count - 1;
+                       this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+               }
+               public override void RemoveChild (Widget child)
+               {
+                       TabItem ti = child as TabItem;
+                       if (ti == null)
+                               throw new Exception ("TabView control accept only TabItem as child.");
+
+                       ti.MouseDown -= Ti_MouseDown;
+                       ti.TabTitle.LayoutChanged -= Ti_TabTitle_LayoutChanged;
+                       ti.tview = null;
+
+                       childrenRWLock.EnterReadLock ();
+
+                       TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
+                       int selTabViewIdx = -1;
+
+                       if (SelectedTab < tabItms.Length && SelectedTab >= 0)
+                               selTabViewIdx = (Children [SelectedTab] as TabItem).ViewIndex;
+
+                       for (int i = selTabViewIdx+1; i < tabItms.Length; i++)
+                               tabItms [i].ViewIndex--;
+
+                       if (selTabViewIdx > tabItms.Length - 2)
+                               selTabViewIdx = tabItms.Length - 2;
+
+                       if (selTabViewIdx < 0)
+                               SelectedTab = -1;
+                       else
+                               SelectedTab = Children.IndexOf (tabItms [selTabViewIdx]);
+
+                       childrenRWLock.ExitReadLock ();
+
+                       base.RemoveChild (child);
+               }
+
+               public override bool ArrangeChildren { get { return true; } }
+               public override bool UpdateLayout (LayoutingType layoutType)
+               {
+                       RegisteredLayoutings &= (~layoutType);
+
+                       if (layoutType == LayoutingType.ArrangeChildren && Children.Count > 0) {
+                               Rectangle cb = ClientRectangle;
+
+                               int tabSpace = tabWidth + leftSlope;
+                               int tc = Children.Count (c => c.Visible == true);
+
+                               if (tc > 0)
+                                       tabSpace = Math.Min(tabSpace, (cb.Width-rightSlope) / tc);
+
+                               if (tabSpace < tabWidth + leftSlope)
+                                       adjustedTab = tabSpace - leftSlope;
+                               else
+                                       adjustedTab = -1;
+
+                               //Console.WriteLine ("tabspace: {0} tw:{1}", tabSpace, tabWidth);
+
+                               childrenRWLock.EnterReadLock();
+                               TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray();
+                               childrenRWLock.ExitReadLock();
+                               int curOffset = leftSlope;
+
+                               for (int i = 0; i < tabItms.Length; i++) {
+                                       if (!tabItms [i].Visible)
+                                               continue;
+                                       tabItms [i].NotifyValueChanged ("TabHeight", tabHeight);
+                                       tabItms [i].NotifyValueChanged ("TabWidth", TabWidth);
+                                       if (!tabItms [i].IsDragged) {
+                                               tabItms [i].TabOffset = curOffset;
+                                               //Console.WriteLine ("offset: {0}=>{1}", tabItms [i].Name, tabItms [i].TabOffset);
+                                       }
+                                       if (Orientation == Orientation.Horizontal) {
+                                               curOffset += tabSpace;
+                                       } else
+                                               curOffset += tabSpace;                                  
+                               }
+
+                               //if no layouting remains in queue for item, registre for redraw
+                               if (RegisteredLayoutings == LayoutingType.None && IsDirty)
+                                       IFace.EnqueueForRepaint (this);
+
+                               return true;
+                       }
+
+                       return base.UpdateLayout(layoutType);
+               }
+               public override void OnLayoutChanges (LayoutingType layoutType)
+               {
+                       if (_orientation == Orientation.Horizontal) {
+                               if (layoutType == LayoutingType.Width)
+                                       RegisterForLayouting (LayoutingType.ArrangeChildren);                           
+                       } else if (layoutType == LayoutingType.Height)
+                               RegisterForLayouting (LayoutingType.ArrangeChildren);                   
+                       
+                       base.OnLayoutChanges (layoutType);
+               }
+
+               protected override void onDraw (Context gr)
+               {
+                       Rectangle rBack = new Rectangle (Slot.Size);
+
+                       Background.SetAsSource (gr, rBack);
+                       CairoHelpers.CairoRectangle(gr,rBack, CornerRadius);
+                       gr.Fill ();
+
+                       gr.Save ();
+
+                       if (ClipToClientRect) {
+                               //clip to client zone
+                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
+                               gr.Clip ();
+                       }
+
+                       childrenRWLock.EnterReadLock ();
+
+                       TabItem[] tabItms = Children.Where(tt=>tt.Visible).Cast<TabItem> ().
+                               OrderBy (t => t.ViewIndex).ToArray ();
+
+                       int selTabViewIdx = -1;
+                       if (SelectedTab < tabItms.Length && SelectedTab >= 0)
+                               selTabViewIdx = (Children [SelectedTab] as TabItem).ViewIndex;
+
+                       childrenRWLock.ExitReadLock ();
+
+                       int i = 0;
+                       while (i < selTabViewIdx) {
+                               tabItms [i].Paint (ref gr);
+                               i++;
+                       }
+                       i = tabItms.Length - 1;
+                       while (i > selTabViewIdx) {
+                               tabItms [i].Paint (ref gr);
+                               i--;
+                       }
+
+                       if (selTabViewIdx >= 0)
+                               tabItms [selTabViewIdx].Paint (ref gr);
+               
+                       gr.Restore ();
+               }
+
+               protected override void onDragEnter (object sender, DragDropEventArgs e)
+               {
+                       base.onDragEnter (sender, e);
+
+                       TabItem ti = e.DragSource as TabItem;
+                       if (ti == null)
+                               return;
+                       if (ti.Parent != null || ti.savedParent == this)
+                               return;
+
+                       this.AddChild (ti);
+
+                       Point p = ScreenPointToLocal (IFace.Mouse.Position) - Margin;
+
+                       p.X = Math.Max (leftSlope, p.X);
+                       p.X = Math.Min (ClientRectangle.Width - rightSlope - TabWidth, p.X);
+                       ti.TabOffset = p.X;
+
+                       IFace.ClearDragImage ();
+
+               }
+
+               void Ti_TabTitle_LayoutChanged (object sender, LayoutingEventArgs e)
+               {
+                       if (e.LayoutType == LayoutingType.X)                            
+                               RegisterForLayouting (LayoutingType.ArrangeChildren);                   
+               }
+               void Ti_MouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       SelectedTab = Children.IndexOf (sender as Widget);
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/TemplatedContainer.cs b/Crow/src/Widgets/TemplatedContainer.cs
new file mode 100644 (file)
index 0000000..0acd876
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Xml.Serialization;
+using System.Xml;
+using System.Reflection;
+
+namespace Crow
+{
+       /// <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
+       {
+               #if DESIGN_MODE
+               public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem)
+               {
+                       if (this.design_isTGItem)
+                               return;
+                       base.getIML (doc, parentElem);
+                       if (!HasContent)
+                               return;
+                       Content.getIML (doc, parentElem.LastChild);
+               }
+               #endif
+
+               #region CTOR
+               protected TemplatedContainer() : base(){}
+               public TemplatedContainer (Interface iface) : base(iface){}
+               #endregion
+
+               protected Container _contentContainer;
+
+               /// <summary>
+               /// Single child of this templated container.
+               /// </summary>
+               public virtual Widget 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(Widget template = null)
+               {
+                       base.loadTemplate (template);
+                       _contentContainer = this.child.FindByName ("Content") as Container;
+               }
+
+               #region GraphicObject overrides
+               public override Widget FindByName (string nameToFind)
+               {
+                       if (Name == nameToFind)
+                               return this;
+
+                       return Content == null ? null : Content.FindByName (nameToFind);
+               }
+               public override bool Contains (Widget goToFind)
+               {
+                       if (Content == goToFind)
+                               return true;
+                       if (Content?.Contains (goToFind) == true)
+                               return true;
+                       return base.Contains (goToFind);
+               }
+               #endregion
+       }
+}
+
diff --git a/Crow/src/Widgets/TemplatedControl.cs b/Crow/src/Widgets/TemplatedControl.cs
new file mode 100644 (file)
index 0000000..563fc0a
--- /dev/null
@@ -0,0 +1,140 @@
+// Copyright (c) 2013-2019  Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using Crow.Cairo;
+
+namespace Crow
+{
+       /// <summary>
+       /// Base class for all templated widget
+       /// </summary>
+       public abstract class TemplatedControl : PrivateContainer
+       {
+               #if DESIGN_MODE
+               public bool design_inlineTemplate = false;
+               public override void getIML (XmlDocument doc, XmlNode parentElem)
+               {
+                       if (this.design_isTGItem)
+                               return;
+                       base.getIML (doc, parentElem);
+                       if (child == null || !design_inlineTemplate)
+                               return;
+                       XmlElement xe = doc.CreateElement("Template");
+                       child.getIML (doc, xe);
+                       parentElem.LastChild.AppendChild (xe);
+               }
+               #endif
+
+               #region CTOR
+               protected TemplatedControl() : base(){}
+               public TemplatedControl (Interface iface) : base(iface){}
+               #endregion
+
+               string _template;
+               string caption;
+
+               /// <summary>
+               /// Template path
+               /// </summary>
+               //TODO: this property should be renamed 'TemplatePath'
+               [DefaultValue(null)]
+               public string Template {
+                       get { return _template; }
+                       set {
+                               if (_template == value)
+                                       return;
+                               _template = value;
+
+                               if (string.IsNullOrEmpty(_template))
+                                       loadTemplate ();
+                               else
+                                       loadTemplate (IFace.CreateTemplateInstance (_template, this.GetType()));
+                       }
+               }
+               /// <summary>
+               /// a caption being recurrent need in templated widget, it is declared here.
+               /// </summary>
+               [DefaultValue("Templated Control")]
+               public virtual string Caption {
+                       get { return caption; }
+                       set {
+                               if (caption == value)
+                                       return;
+                               caption = value;
+                               NotifyValueChanged ("Caption", caption);
+                       }
+               }
+
+               #region GraphicObject overrides
+
+               public override void Initialize ()
+               {
+                       loadTemplate ();
+                       base.Initialize ();
+               }
+               /// <summary>
+               /// override search method from GraphicObject to prevent
+               /// searching inside template
+               /// </summary>
+               /// <returns>widget identified by name, or null if not found</returns>
+               /// <param name="nameToFind">widget's name to find</param>
+               public override Widget FindByName (string nameToFind) => nameToFind == this.Name ? this : null;
+
+               /// <summary>
+               ///onDraw is overrided to prevent default drawing of background, template top container
+               ///may have a binding to root background or a fixed one.
+               ///this allow applying root background to random template's component
+               /// </summary>
+               /// <param name="gr">Backend context</param>
+               protected override void onDraw (Context gr)
+               {
+                       gr.Save ();
+
+                       if (ClipToClientRect) {
+                               //clip to client zone
+                               CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
+                               gr.Clip ();
+                       }
+
+                       if (child != null)
+                               child.Paint (ref gr);
+                       gr.Restore ();
+               }
+               #endregion
+
+               /// <summary>
+               /// Loads the template. Each TemplatedControl MUST provide a default template
+               /// It must be an embedded ressource with ID = fullTypeName.template
+               /// Entry assembly is search first, then the one where the type is defined
+               /// </summary>
+               /// <param name="template">Optional template instance</param>
+               protected virtual void loadTemplate(Widget template = null)
+               {
+                       if (this.child != null)//template change, bindings has to be reset
+                               this.ClearTemplateBinding();
+                       
+                       if (template == null) {
+                               int mdTok = this.GetType ().MetadataToken;
+
+                               if (!IFace.DefaultTemplates.ContainsKey (mdTok)) {
+                                       string defTmpId = this.GetType ().FullName + ".template";
+                                       Stream s = Assembly.GetEntryAssembly ().GetManifestResourceStream (defTmpId);
+                                       if (s == null)
+                                               s = Assembly.GetAssembly (this.GetType ()).GetManifestResourceStream (defTmpId);
+                                       if (s == null)
+                                               throw new Exception (string.Format ("No default template found for '{0}'", this.GetType ().FullName));
+                                       IFace.DefaultTemplates [mdTok] = new IML.Instantiator (IFace, s, defTmpId);
+                               }
+                               this.SetChild (IFace.DefaultTemplates[mdTok].CreateInstance());
+                       }else
+                               this.SetChild (template);
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/TemplatedGroup.cs b/Crow/src/Widgets/TemplatedGroup.cs
new file mode 100644 (file)
index 0000000..da87b91
--- /dev/null
@@ -0,0 +1,530 @@
+//
+// TemplatedGroup.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.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading;
+using Crow.IML;
+
+namespace Crow {
+       public abstract class TemplatedGroup : TemplatedControl
+       {
+               #if DESIGN_MODE
+               public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem)
+               {
+                       if (this.design_isTGItem)
+                               return;
+                       base.getIML (doc, parentElem);
+
+                       if (string.IsNullOrEmpty(_itemTemplate)) {
+                               foreach (ItemTemplate it in ItemTemplates.Values) 
+                                       it.getIML (doc, parentElem.LastChild);                          
+                       }
+
+                       foreach (Widget g in Items) {
+                               g.getIML (doc, parentElem.LastChild);   
+                       }
+               }
+               #endif
+
+               #region CTOR
+               protected TemplatedGroup() : base(){}
+               public TemplatedGroup (Interface iface) : base(iface){}
+               #endregion
+
+               protected Group items;
+               string _itemTemplate, dataTest;
+
+               #region events
+               public event EventHandler<SelectionChangeEventArgs> SelectedItemChanged;
+               public event EventHandler Loaded;
+               #endregion
+
+               IEnumerable data;
+               int _selectedIndex = -1;
+               Color selBackground, selForeground;
+
+               int itemPerPage = 50;
+               CrowThread loadingThread = null;
+
+               bool isPaged = false;
+
+               #region Templating
+               //TODO: dont instantiate ItemTemplates if not used
+               //but then i should test if null in msil gen
+               public Dictionary<string, ItemTemplate> ItemTemplates = new Dictionary<string, ItemTemplate>();
+
+               /// <summary>
+               /// Keep track of expanded subnodes and closed time to unload
+               /// </summary>
+               //Dictionary<GraphicObject, Stopwatch> nodes = new Dictionary<GraphicObject, Stopwatch>();
+               internal List<Widget> nodes = new List<Widget>();
+               /// <summary>
+               /// 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>          
+               public string ItemTemplate {
+                       get { return _itemTemplate; }
+                       set {
+                               if (value == _itemTemplate)
+                                       return;
+
+                               _itemTemplate = value;
+
+                               //TODO:reload list with new template?
+                               NotifyValueChanged("ItemTemplate", _itemTemplate);
+                       }
+               }
+               protected override void loadTemplate(Widget template = null)
+               {
+                       base.loadTemplate (template);
+
+                       items = this.child.FindByName ("ItemsContainer") as Group;
+                       if (items == null)
+                               throw new Exception ("TemplatedGroup template Must contain a Group named 'ItemsContainer'");
+                       if (items.Children.Count == 0)
+                               NotifyValueChanged ("HasChildren", false);
+                       else
+                               NotifyValueChanged ("HasChildren", true);
+               }
+               /// <summary>
+               /// Use to define condition on Data item for selecting among ItemTemplates.
+               /// Default value is 'TypeOf' for selecting Template depending on Type of Data.
+               /// Other possible values are properties of Data
+               /// </summary>
+               /// <value>The data property test.</value>
+               [DefaultValue("TypeOf")]
+               public string DataTest {
+                       get { return dataTest; }
+                       set {
+                               if (value == dataTest)
+                                       return;
+
+                               dataTest = value;
+
+                               NotifyValueChanged("DataTest", dataTest);
+                       }
+               }
+               #endregion
+
+               public virtual List<Widget> Items{
+                       get {
+                               return isPaged ? items.Children.SelectMany(x => (x as Group).Children).ToList()
+                               : items.Children;
+                       }
+               }
+               [DefaultValue(-1)]public virtual int SelectedIndex{
+                       get { return _selectedIndex; }
+                       set {
+                               if (value == _selectedIndex)
+                                       return;
+
+                               /*if (_selectedIndex >= 0 && Items.Count > _selectedIndex) {
+                                       Items[_selectedIndex].Foreground = Color.Transparent;
+                                       Items[_selectedIndex].Background = Color.Transparent;
+                               }*/
+
+                               _selectedIndex = value;
+
+                               /*if (_selectedIndex >= 0 && Items.Count > _selectedIndex) {
+                                       Items[_selectedIndex].Foreground = SelectionForeground;
+                                       Items[_selectedIndex].Background = SelectionBackground;
+                               }*/
+
+                               NotifyValueChanged ("SelectedIndex", _selectedIndex);
+                               NotifyValueChanged ("SelectedItem", SelectedItem);
+                               SelectedItemChanged.Raise (this, new SelectionChangeEventArgs (SelectedItem));
+                       }
+               }
+               [XmlIgnore]public virtual object SelectedItem{
+                       get { return data == null ? null : _selectedIndex < 0 ? data.GetDefaultValue() : ((IList)data)?[_selectedIndex]; }
+                       set {
+                               if (data == null) {
+                                       SelectedIndex = -1;
+                                       return;
+                               }
+                               //TODO:double check if value type will be notified to binding sys
+                               if (value == SelectedItem)
+                                       return;
+                               
+                               SelectedIndex = (int)((IList)data)?.IndexOf (value);
+                       }
+               }
+               [XmlIgnore]public bool HasItems {
+                       get { return Items.Count > 0; }
+               }
+               public IEnumerable Data {
+                       get { return data; }
+                       set {
+                               if (value == data)
+                                       return;
+
+                               cancelLoadingThread ();
+
+                               if (data is IObservableList) {
+                                       IObservableList ol = data as IObservableList;
+                                       ol.ListAdd -= Ol_ListAdd;
+                                       ol.ListRemove -= Ol_ListRemove;
+                               }
+
+                               data = value;
+
+                               if (data is IObservableList) {
+                                       IObservableList ol = data as IObservableList;
+                                       ol.ListAdd += Ol_ListAdd;
+                                       ol.ListRemove += Ol_ListRemove;
+                               }
+
+                               NotifyValueChanged ("Data", data);
+
+                               lock (IFace.UpdateMutex)
+                                       ClearItems ();
+
+                               if (data == null)
+                                       return;
+
+                               loadingThread = new CrowThread (this, loading);
+                               loadingThread.Finished += (object sender, EventArgs e) => (sender as TemplatedGroup).Loaded.Raise (sender, e);
+                               loadingThread.Start ();
+
+                               NotifyValueChanged ("SelectedIndex", _selectedIndex);
+                               NotifyValueChanged ("SelectedItem", SelectedItem);
+                               SelectedItemChanged.Raise (this, new SelectionChangeEventArgs (SelectedItem));
+                               NotifyValueChanged ("HasItems", HasItems);
+                       }
+               }
+
+               void Ol_ListRemove (object sender, ListChangedEventArg e)
+               {
+                       if (this.isPaged) {
+                               int p = e.Index / itemPerPage;
+                               int i = e.Index % itemPerPage;
+                               (items.Children [p] as Group).DeleteChild (i);
+                       } else
+                               items.DeleteChild (e.Index);
+               }
+
+               void Ol_ListAdd (object sender, ListChangedEventArg e)
+               {
+                       if (this.isPaged) {
+                               throw new NotImplementedException();
+//                             int p = e.Index / itemPerPage;
+//                             int i = e.Index % itemPerPage;
+//                             (items.Children [p] as Group).InsertChild (i, e.Element);
+                       } else
+                               loadItem (e.Element, items, dataTest);
+               }
+
+               [DefaultValue("SteelBlue")]
+               public virtual Color SelectionBackground {
+                       get { return selBackground; }
+                       set {
+                               if (value == selBackground)
+                                       return;
+                               selBackground = value;
+                               NotifyValueChanged ("SelectionBackground", selBackground);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue("White")]
+               public virtual Color SelectionForeground {
+                       get { return selForeground; }
+                       set {
+                               if (value == selForeground)
+                                       return;
+                               selForeground = value;
+                               NotifyValueChanged ("SelectionForeground", selForeground);
+                               RegisterForRedraw ();
+                       }
+               }
+
+               protected void raiseSelectedItemChanged(){
+                       SelectedItemChanged.Raise (this, new SelectionChangeEventArgs (SelectedItem));
+               }
+
+
+               public virtual void AddItem(Widget g){
+                       items.AddChild (g);
+                       g.LogicalParent = this;
+                       NotifyValueChanged ("HasChildren", true);
+               }
+               public virtual void RemoveItem(Widget g)
+               {
+                       g.LogicalParent = null;
+                       items.DeleteChild (g);
+                       if (items.Children.Count == 0)
+                               NotifyValueChanged ("HasChildren", false);
+               }
+
+               public virtual void ClearItems()
+               {
+                       _selectedIndex = -1;
+                       NotifyValueChanged ("SelectedIndex", _selectedIndex);
+                       NotifyValueChanged ("SelectedItem", null);
+
+                       items.ClearChildren ();
+                       NotifyValueChanged ("HasChildren", false);
+               }
+
+
+               #region GraphicObject overrides
+               public override Widget FindByName (string nameToFind)
+               {
+                       if (Name == nameToFind)
+                               return this;
+
+                       foreach (Widget w in Items) {
+                               Widget r = w.FindByName (nameToFind);
+                               if (r != null)
+                                       return r;
+                       }
+                       return null;
+               }
+               public override bool Contains (Widget goToFind)
+               {
+                       foreach (Widget w in Items) {
+                               if (w == goToFind)
+                                       return true;
+                               if (w.Contains (goToFind))
+                                       return true;
+                       }
+                       return base.Contains(goToFind);
+               }
+//             public override void ClearBinding ()
+//             {
+//                     if (items != null)
+//                             items.ClearBinding ();
+//
+//                     base.ClearBinding ();
+//             }
+//             public override void ResolveBindings ()
+//             {
+//                     base.ResolveBindings ();
+//                     if (items != null)
+//                             items.ResolveBindings ();
+//             }
+               #endregion
+
+               /// <summary>
+               /// Items loading thread
+               /// </summary>
+               void loading(){
+                       try {
+                               loadPage (data, items, dataTest);
+                       } catch {
+                               if (Monitor.IsEntered (IFace.LayoutMutex))
+                                       Monitor.Exit (IFace.LayoutMutex);
+                               Console.WriteLine ("loading thread aborted");
+                       }
+
+               }
+//                     //if (!ItemTemplates.ContainsKey ("default"))
+//                     //      ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
+//
+//                     for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) {
+//                             if ((bool)loadingThread?.cancelRequested) {
+//                                     this.Dispose ();
+//                                     return;
+//                             }
+//                             loadPage (i);
+//                             Thread.Sleep (1);
+//                     }
+//             }
+               void cancelLoadingThread(){
+                       if (loadingThread != null)
+                               loadingThread.Cancel ();
+               }
+               void loadPage(IEnumerable _data, Group page, string _dataTest)
+               {
+                       #if DEBUG_LOAD
+                       Stopwatch loadingTime = Stopwatch.StartNew ();
+                       #endif
+
+
+//                     if (typeof(TabView).IsAssignableFrom (items.GetType ())||
+//                             typeof(Menu).IsAssignableFrom (this.GetType())||
+//                             typeof(Wrapper).IsAssignableFrom (items.GetType ())) {
+                               //page = items;
+                               itemPerPage = int.MaxValue;
+                       //                      } else if (typeof(GenericStack).IsAssignableFrom (items.GetType ())) {
+                       //                              GenericStack gs = new GenericStack (items.CurrentInterface);
+                       //                              gs.Orientation = (items as GenericStack).Orientation;
+                       //                              gs.Width = items.Width;
+                       //                              gs.Height = items.Height;
+                       //                              gs.VerticalAlignment = items.VerticalAlignment;
+                       //                              gs.HorizontalAlignment = items.HorizontalAlignment;
+                       //                              page = gs;
+                       //                              page.Name = "page" + pageNum;
+                       //                              isPaged = true;
+                       //                      } else {
+                       //                              page = Activator.CreateInstance (items.GetType ()) as Group;
+                       //                              page.CurrentInterface = items.CurrentInterface;
+                       //                              page.Initialize ();
+                       //                              page.Name = "page" + pageNum;
+                       //                              isPaged = true;
+                       //                      }
+
+                       if (_data == null)
+                               return;
+
+                       foreach (object d in _data) {
+                               loadItem (d, page, _dataTest);
+                               if (loadingThread.cancelRequested)
+                                       break;
+                       }
+
+//                     if (page == items)
+//                             return;
+//                     lock (CurrentInterface.LayoutMutex)
+//                             items.AddChild (page);
+
+#if DEBUG_LOAD
+                       loadingTime.Stop ();
+                       using (StreamWriter sw = new StreamWriter ("loading.log", true)) {
+                               sw.WriteLine ($"NEW ;{this.ToString(),-50};{loadingTime.ElapsedTicks,8};{loadingTime.ElapsedMilliseconds,8}");
+                       }
+#endif
+               }
+
+               protected void loadItem(object o, Group page, string _dataTest){
+                       if (o == null)//TODO:surely a threading sync problem
+                               return;
+                       Widget g = null;
+                       ItemTemplate iTemp = null;
+                       Type dataType = o.GetType ();
+                       string itempKey = dataType.FullName;
+
+                       //if item template selection is not done depending on the type of item
+                       //dataTest must contains a member name of the item 
+                       if (_dataTest != "TypeOf") {
+                               try {
+                                       itempKey = CompilerServices.getValue (dataType, o, _dataTest)?.ToString ();
+                               } catch {
+                                       itempKey = dataType.FullName;
+                               }
+                       }
+
+                       if (ItemTemplates.ContainsKey (itempKey))
+                               iTemp = ItemTemplates [itempKey];
+                       else {
+                               foreach (string it in ItemTemplates.Keys) {
+                                       if (it == "default")
+                                               continue;
+                                       Type t = CompilerServices.getTypeFromName (it);
+                                       if (t == null)
+                                               continue;
+                                       if (t.IsAssignableFrom (dataType)) {//TODO:types could be cached
+                                               iTemp = ItemTemplates [it];
+                                               break;
+                                       }
+                               }
+                               if (iTemp == null)
+                                       iTemp = ItemTemplates ["default"];
+                       }
+
+                       Monitor.Enter (IFace.LayoutMutex);
+                               g = iTemp.CreateInstance();
+                               #if DESIGN_MODE
+                               g.design_isTGItem = true;
+                               #endif
+                               page.AddChild (g);
+//                             if (isPaged)
+                               g.LogicalParent = this;
+                               g.MouseClick += itemClick;
+                       Monitor.Exit (IFace.LayoutMutex);
+
+                       if (iTemp.Expand != null && g is Expandable) {
+                               Expandable e = g as Expandable;
+                               e.Expand += iTemp.Expand;
+                               if ((o as ICollection) == null)
+                                       e.GetIsExpandable = new BooleanTestOnInstance((instance) => true);
+                               else
+                                       e.GetIsExpandable = iTemp.HasSubItems;
+                       }
+
+                       g.DataSource = o;
+               }
+
+
+               //              protected void _list_LayoutChanged (object sender, LayoutingEventArgs e)
+               //              {
+               //                      #if DEBUG_LAYOUTING
+               //                      Debug.WriteLine("list_LayoutChanged");
+               //                      #endif
+               //                      if (_gsList.Orientation == Orientation.Horizontal) {
+               //                              if (e.LayoutType == LayoutingType.Width)
+               //                                      _gsList.Width = approxSize;
+               //                      } else if (e.LayoutType == LayoutingType.Height)
+               //                              _gsList.Height = approxSize;
+               //              }
+               int approxSize
+               {
+                       get {
+                               if (data == null)
+                                       return -1;
+                               GenericStack page1 = items.FindByName ("page1") as GenericStack;
+                               if (page1 == null)
+                                       return -1;
+
+                               return page1.Orientation == Orientation.Horizontal ?
+                                       (data as ICollection)?.Count < itemPerPage ?
+                                       -1:
+                                       (int)Math.Ceiling ((double)page1.Slot.Width / (double)itemPerPage * (double)((data as ICollection)?.Count+1)):
+                                       (data as ICollection)?.Count < itemPerPage ?
+                                       -1:
+                                       (int)Math.Ceiling ((double)page1.Slot.Height / (double)itemPerPage * (double)((data as ICollection)?.Count+1));
+                       }
+               }
+               internal virtual void itemClick(object sender, MouseButtonEventArgs e){
+                       SelectedIndex = (int)((IList)data)?.IndexOf((sender as Widget).DataSource);
+               }
+
+               bool emitHelperIsAlreadyExpanded (Widget go){
+                       if (nodes.Contains (go))
+                               return true;
+                       nodes.Add (go);
+                       return false;
+               }
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (disposing && loadingThread != null)
+                               loadingThread.Cancel ();
+                       base.Dispose (disposing);
+               }
+
+               public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
+               {
+                       base.OnDataSourceChanged (sender, e);
+               }
+       }
+}
diff --git a/Crow/src/Widgets/TestCairoPatch.cs b/Crow/src/Widgets/TestCairoPatch.cs
new file mode 100644 (file)
index 0000000..f8294a3
--- /dev/null
@@ -0,0 +1,148 @@
+//
+// TestCairoPatch.cs
+//
+// Author:
+//       jp <>
+//
+// 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 Crow.Cairo;
+
+namespace Crow
+{
+       public class TestCairoPatch : Widget
+       {
+               void computeControlPoints (
+                       double xc, double yc,
+                       double x1, double y1,
+                       out double x2, out double y2,
+                       out double x3, out double y3,
+                       double x4, double y4){
+                       double ax = x1 - xc;
+                       double ay = y1 - yc;
+                       double bx = x4 - xc;
+                       double byy = y4 - yc;
+                       double q1 = ax * ax + ay * ay;
+                       double q2 = q1 + ax * bx + ay * byy;
+                       double k2 = 4.0/3.0 * (Math.Sqrt(2.0 * q1 * q2) - q2) / (ax * byy - ay * bx);
+
+
+                       x2 = xc + ax - k2 * ay;
+                       y2 = yc + ay + k2 * ax;
+                       x3 = xc + bx + k2 * byy;
+                       y3 = yc + byy - k2 * bx;
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       double radius = Math.Min (ClientRectangle.Width, ClientRectangle.Height) / 2;
+
+                       double pi3 = Math.PI / 3.0;
+
+                       MeshPattern mp = new MeshPattern ();
+
+                       double x1 = radius,y1 = 0,
+                       x2 = 0, y2 = 0, x3 = 0, y3 = 0, x4 = 0, y4 = 0,
+                       xc = radius,yc = radius;
+
+                       double dx = Math.Sin (pi3) * radius;
+                       double dy = Math.Cos (pi3) * radius;
+
+                       mp.BeginPatch ();
+                       mp.MoveTo (xc, yc);
+                       mp.LineTo (x1, y1);
+                       x4 = xc + dx;
+                       y4 = yc - dy;
+                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
+                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
+
+                       mp.SetCornerColorRGB (0, 1, 1, 1);
+                       mp.SetCornerColorRGB (1, 1, 0, 0);
+                       mp.SetCornerColorRGB (2, 1, 1, 0);
+
+                       x1 = x4;
+                       y1 = y4;
+                       y4 = yc + dy;
+
+                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
+                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
+
+                       mp.SetCornerColorRGB (3, 0, 1, 0);
+                       mp.EndPatch ();
+
+                       x1 = x4;
+                       y1 = y4;
+                       x4 = xc;
+                       y4 = yc * 2.0;
+
+                       mp.BeginPatch ();
+                       mp.MoveTo (xc, yc);
+                       mp.LineTo (x1, y1);
+                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
+                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
+
+                       mp.SetCornerColorRGB (0, 1, 1, 1);
+                       mp.SetCornerColorRGB (1, 0, 1, 0);
+                       mp.SetCornerColorRGB (2, 0, 1, 1);
+
+                       x1 = x4;
+                       y1 = y4;
+                       x4 = xc-dx;
+                       y4 = yc+dy;
+
+                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
+                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
+
+                       mp.SetCornerColorRGB (3, 0, 0, 1);
+                       mp.EndPatch ();
+
+                       x1 = x4;
+                       y1 = y4;
+                       y4 = yc - dy;
+
+                       mp.BeginPatch ();
+                       mp.MoveTo (xc, yc);
+                       mp.LineTo (x1, y1);
+                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
+                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
+
+                       mp.SetCornerColorRGB (0, 1, 1, 1);
+                       mp.SetCornerColorRGB (1, 0, 0, 1);
+                       mp.SetCornerColorRGB (2, 1, 0, 1);
+
+                       x1 = x4;
+                       y1 = y4;
+                       x4 = radius;
+                       y4 = 0;
+
+                       computeControlPoints (xc, yc, x1, y1, out x2, out y2, out x3, out y3, x4, y4);
+                       mp.CurveTo (x2, y2, x3, y3, x4, y4);
+
+                       mp.SetCornerColorRGB (3, 1, 0, 0);
+                       mp.EndPatch ();
+
+                       gr.SetSource (mp);
+                       gr.Paint ();
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/TextBox.cs b/Crow/src/Widgets/TextBox.cs
new file mode 100644 (file)
index 0000000..71fd620
--- /dev/null
@@ -0,0 +1,228 @@
+//
+// TextBox.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 Crow.Cairo;
+using System.Diagnostics;
+using System.Xml.Serialization;
+
+namespace Crow
+{
+    public class TextBox : Label
+    {
+               #region CTOR
+               protected TextBox() : base(){}
+               public TextBox(Interface iface) : base(iface)
+               { }
+//             public TextBox(string _initialValue)
+//                     : base(_initialValue)
+//             {
+//
+//             }
+               #endregion
+
+               #region GraphicObject overrides
+               [XmlIgnore]public override bool HasFocus   //trigger update when lost focus to errase text beam
+        {
+            get
+            {
+                return base.HasFocus;
+            }
+            set
+            {
+                base.HasFocus = value;
+                RegisterForRedraw();
+            }
+        }
+
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+                       FontExtents fe = gr.FontExtents;
+               }
+               #endregion
+                       
+        #region Keyboard handling
+               public override void onKeyDown (object sender, KeyEventArgs e)
+               {
+                       base.onKeyDown (sender, e);
+
+                       Key key = e.Key;
+
+                       switch (key)
+                       {
+                       case Key.BackSpace:
+                               if (CurrentPosition == 0)
+                                       return;
+                               this.DeleteChar();
+                               break;
+                       case Key.Clear:
+                               break;
+                       case Key.Delete:
+                               if (selectionIsEmpty) {
+                                       if (!MoveRight ())
+                                               return;
+                               }else if (IFace.Shift)
+                                       IFace.Clipboard = this.SelectedText;
+                               this.DeleteChar ();
+                               break;
+                       case Key.KP_Enter:
+                       case Key.Return:
+                               if (!selectionIsEmpty)
+                                       this.DeleteChar ();
+                               if (Multiline)
+                                       this.InsertLineBreak ();
+                               else
+                                       OnTextChanged(this,new TextChangeEventArgs(Text));
+                               break;
+                       case Key.Escape:
+                               Text = "";
+                               CurrentColumn = 0;
+                               SelRelease = -1;
+                               break;
+                       case Key.Home:
+                               if (IFace.Shift) {
+                                       if (selectionIsEmpty)
+                                               SelBegin = new Point (CurrentColumn, CurrentLine);
+                                       if (IFace.Ctrl)
+                                               CurrentLine = 0;
+                                       CurrentColumn = 0;
+                                       SelRelease = new Point (CurrentColumn, CurrentLine);
+                                       break;
+                               }
+                               SelRelease = -1;
+                               if (IFace.Ctrl)
+                                       CurrentLine = 0;
+                               CurrentColumn = 0;
+                               break;
+                       case Key.End:
+                               if (IFace.Shift) {
+                                       if (selectionIsEmpty)
+                                               SelBegin = CurrentPosition;
+                                       if (IFace.Ctrl)
+                                               CurrentLine = int.MaxValue;
+                                       CurrentColumn = int.MaxValue;
+                                       SelRelease = CurrentPosition;
+                                       break;
+                               }
+                               SelRelease = -1;
+                               if (IFace.Ctrl)
+                                       CurrentLine = int.MaxValue;
+                               CurrentColumn = int.MaxValue;
+                               break;
+                       case Key.Insert:
+                               if (IFace.Shift)
+                                       this.Insert (IFace.Clipboard);
+                               else if (IFace.Ctrl && !selectionIsEmpty)
+                                       IFace.Clipboard = this.SelectedText;
+                               break;
+                       case Key.Left:
+                               if (IFace.Shift) {
+                                       if (selectionIsEmpty)
+                                               SelBegin = new Point(CurrentColumn, CurrentLine);
+                                       if (IFace.Ctrl)
+                                               GotoWordStart ();
+                                       else if (!MoveLeft ())
+                                               return;
+                                       SelRelease = CurrentPosition;
+                                       break;
+                               }
+                               SelRelease = -1;
+                               if (IFace.Ctrl)
+                                       GotoWordStart ();
+                               else
+                                       MoveLeft();
+                               break;
+                       case Key.Right:
+                               if (IFace.Shift) {
+                                       if (selectionIsEmpty)
+                                               SelBegin = CurrentPosition;
+                                       if (IFace.Ctrl)
+                                               GotoWordEnd ();
+                                       else if (!MoveRight ())
+                                               return;
+                                       SelRelease = CurrentPosition;
+                                       break;
+                               }
+                               SelRelease = -1;
+                               if (IFace.Ctrl)
+                                       GotoWordEnd ();
+                               else
+                                       MoveRight ();
+                               break;
+                       case Key.Up:
+                               if (IFace.Shift) {
+                                       if (selectionIsEmpty)
+                                               SelBegin = CurrentPosition;
+                                       CurrentLine--;
+                                       SelRelease = CurrentPosition;
+                                       break;
+                               }
+                               SelRelease = -1;
+                               CurrentLine--;
+                               break;
+                       case Key.Down:
+                               if (IFace.Shift) {
+                                       if (selectionIsEmpty)
+                                               SelBegin = CurrentPosition;
+                                       CurrentLine++;
+                                       SelRelease = CurrentPosition;
+                                       break;
+                               }
+                               SelRelease = -1;
+                               CurrentLine++;                          
+                               break;
+                       case Key.Menu:
+                               break;
+                       case Key.Num_Lock:
+                               break;
+                       case Key.Page_Down:                             
+                               break;
+                       case Key.Page_Up:
+                               break;
+                       case Key.Tab:
+                               this.Insert ("\t");
+                               break;
+                       default:
+                               break;
+                       }
+
+                       RegisterForGraphicUpdate();
+               }
+               public override void onKeyPress (object sender, KeyPressEventArgs e)
+               {
+                       base.onKeyPress (sender, e);
+
+                       this.Insert (e.KeyChar.ToString());
+
+                       SelRelease = -1;
+                       SelBegin = new Point(CurrentColumn, SelBegin.Y);
+
+                       RegisterForGraphicUpdate();
+               }
+        #endregion
+       } 
+}
diff --git a/Crow/src/Widgets/TextRun.cs b/Crow/src/Widgets/TextRun.cs
new file mode 100644 (file)
index 0000000..f784f90
--- /dev/null
@@ -0,0 +1,307 @@
+//
+// TextRun.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.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using Crow.Cairo;
+using System.Text.RegularExpressions;
+using System.Xml.Serialization;
+using System.ComponentModel;
+
+namespace Crow
+{
+       [DesignIgnore]
+       public class TextRun : Widget
+       {
+               #region CTOR
+               protected TextRun () : base(){}
+               public TextRun (Interface iface) : base (iface){}
+               #endregion
+
+               //TODO:change protected to private
+
+               #region private and protected fields
+               protected string _text = "label";
+               Alignment _textAlignment = Alignment.Left;
+               bool horizontalStretch = false;
+               bool verticalStretch = false;
+               bool _multiline;
+               bool wordWrap;
+               protected Rectangle rText;
+               protected float widthRatio = 1f;
+               protected float heightRatio = 1f;
+               protected FontExtents fe;
+               protected TextExtents te;
+               #endregion
+
+
+               
+               [DefaultValue (Alignment.Left)]
+               public Alignment TextAlignment {
+                       get { return _textAlignment; }
+                       set { _textAlignment = value; }
+               }
+               
+               [DefaultValue (false)]
+               public virtual bool HorizontalStretch {
+                       get { return horizontalStretch; }
+                       set {
+                               if (horizontalStretch == value)
+                                       return;
+                               horizontalStretch = value;
+                               RegisterForRedraw ();
+                               NotifyValueChanged ("HorizontalStretch", horizontalStretch);
+                       }
+               }
+               
+               [DefaultValue (false)]
+               public virtual bool VerticalStretch {
+                       get { return verticalStretch; }
+                       set {
+                               if (verticalStretch == value)
+                                       return;
+                               verticalStretch = value;
+                               RegisterForRedraw ();
+                               NotifyValueChanged ("VerticalStretch", verticalStretch);
+                       }
+               }
+               
+               [DefaultValue ("label")]
+               public string Text {
+                       get {
+                               return lines == null ?
+                                       _text : lines.Aggregate ((i, j) => i + Interface.LineBreak + j);
+                       }
+                       set {
+                               if (_text == value)
+                                       return;
+
+                               RegisterForGraphicUpdate ();
+
+                               _text = value;
+
+                               if (string.IsNullOrEmpty (_text))
+                                       _text = "";
+
+                               lines = getLines;
+                       }
+               }
+               
+               [DefaultValue (false)]
+               public bool Multiline {
+                       get { return _multiline; }
+                       set {
+                               _multiline = value;
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               
+               [DefaultValue (false)]
+               public bool WordWrap {
+                       get {
+                               return wordWrap;
+                       }
+                       set {
+                               if (wordWrap == value)
+                                       return;
+                               wordWrap = value;
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+
+               List<string> lines;
+               List<string> getLines {
+                       get {
+                               return _multiline ?
+                                       Regex.Split (_text, "\r\n|\r|\n").ToList () :
+                                       new List<string> (new string [] { _text });
+                       }
+               }
+
+               #region GraphicObject overrides
+               protected override int measureRawSize (LayoutingType lt)
+               {
+                       if (lines == null)
+                               lines = getLines;
+                               
+                       using (Context gr = new Context (IFace.surf)) {
+                               //Cairo.FontFace cf = gr.GetContextFontFace ();
+
+                               gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+                               gr.SetFontSize (Font.Size);
+
+
+                               fe = gr.FontExtents;
+                               te = new TextExtents ();
+
+                               if (lt == LayoutingType.Height) {
+                                       int lc = lines.Count;
+                                       //ensure minimal height = text line height
+                                       if (lc == 0)
+                                               lc = 1;
+
+                                       return (int)(fe.Height * lc) + Margin * 2;
+                               }
+
+                               foreach (string s in lines) {
+                                       string l = s.Replace("\t", new String (' ', Interface.TAB_SIZE));
+                                       TextExtents tmp = gr.TextExtents (l);
+                                       if (tmp.XAdvance > te.XAdvance)
+                                               te = tmp;
+                               }
+                               return (int)Math.Ceiling (te.XAdvance) + Margin * 2;
+                       }
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+                       gr.SetFontSize (Font.Size);
+                       gr.FontOptions = Interface.FontRenderingOptions;
+                       gr.Antialias = Interface.Antialias;
+
+                       rText = new Rectangle (new Size (
+                               measureRawSize (LayoutingType.Width), measureRawSize (LayoutingType.Height)));
+                       rText.Width -= 2 * Margin;
+                       rText.Height -= 2 * Margin;
+
+                       widthRatio = 1f;
+                       heightRatio = 1f;
+
+                       Rectangle cb = ClientRectangle;
+
+                       //ignore text alignment if size to content = true
+                       //or if text size is larger than client bounds
+                       if (Width < 0 || Height < 0 || rText.Width > cb.Width) {
+                               rText.X = cb.X;
+                               rText.Y = cb.Y;
+                       } else {
+                               if (horizontalStretch) {
+                                       widthRatio = (float)cb.Width / rText.Width;
+                                       if (!verticalStretch)
+                                               heightRatio = widthRatio;
+                               }
+                               if (verticalStretch) {
+                                       heightRatio = (float)cb.Height / rText.Height;
+                                       if (!horizontalStretch)
+                                               widthRatio = heightRatio;
+                               }
+
+                               rText.Width = (int)(widthRatio * cb.Width);
+                               rText.Height = (int)(heightRatio * cb.Height);
+
+                               switch (TextAlignment) {
+                               case Alignment.TopLeft:     //ok
+                                       rText.X = cb.X;
+                                       rText.Y = cb.Y;
+                                       break;
+                               case Alignment.Top:   //ok                                              
+                                       rText.Y = cb.Y;
+                                       rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
+                                       break;
+                               case Alignment.TopRight:    //ok
+                                       rText.Y = cb.Y;
+                                       rText.X = cb.Right - rText.Width;
+                                       break;
+                               case Alignment.Left://ok
+                                       rText.X = cb.X;
+                                       rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
+                                       break;
+                               case Alignment.Right://ok
+                                       rText.X = cb.X + cb.Width - rText.Width;
+                                       rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
+                                       break;
+                               case Alignment.Bottom://ok
+                                       rText.X = cb.Width / 2 - rText.Width / 2;
+                                       rText.Y = cb.Height - rText.Height;
+                                       break;
+                               case Alignment.BottomLeft://ok
+                                       rText.X = cb.X;
+                                       rText.Y = cb.Bottom - rText.Height;
+                                       break;
+                               case Alignment.BottomRight://ok
+                                       rText.Y = cb.Bottom - rText.Height;
+                                       rText.X = cb.Right - rText.Width;
+                                       break;
+                               case Alignment.Center://ok
+                                       rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
+                                       rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
+                                       break;
+                               }
+                       }
+
+                       gr.FontMatrix = new Matrix (widthRatio * Font.Size, 0, 0, heightRatio * Font.Size, 0, 0);
+
+
+                       int curLineCount = 0;
+                       for (int i = 0; i < lines.Count; i++) {
+                               string l = lines [i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
+                               List<string> wl = new List<string> ();
+                               int lineLength = (int)gr.TextExtents (l).XAdvance;
+
+                               if (wordWrap && lineLength > cb.Width) {
+                                       string tmpLine = "";
+                                       int curChar = 0;
+                                       while (curChar < l.Length) {
+                                               tmpLine += l [curChar];
+                                               if ((int)gr.TextExtents (tmpLine).XAdvance > cb.Width) {
+                                                       tmpLine = tmpLine.Remove (tmpLine.Length - 1);
+                                                       wl.Add (tmpLine);
+                                                       tmpLine = "";
+                                                       continue;
+                                               }
+                                               curChar++;
+                                       }
+                                       wl.Add (tmpLine);
+                               } else
+                                       wl.Add (l);
+
+                               foreach (string ll in wl) {
+                                       lineLength = (int)gr.TextExtents (ll).XAdvance;
+
+
+                                       if (string.IsNullOrWhiteSpace (ll)) {
+                                               curLineCount++;
+                                               continue;
+                                       }
+
+                                       Foreground.SetAsSource (gr);
+                                       gr.MoveTo (rText.X, rText.Y + fe.Ascent + fe.Height * curLineCount);
+
+                                       gr.ShowText (ll);
+                                       gr.Fill ();
+
+                                       curLineCount++;
+                               }
+                       }
+               }
+               #endregion
+       }
+}
diff --git a/Crow/src/Widgets/TreeView.cs b/Crow/src/Widgets/TreeView.cs
new file mode 100644 (file)
index 0000000..af86ab7
--- /dev/null
@@ -0,0 +1,108 @@
+//
+// TreeView.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.Xml.Serialization;
+using System.Diagnostics;
+using System.ComponentModel;
+
+namespace Crow
+{
+       //treeview expect expandable child (or not)
+       //if their are expandable, some functions and events are added
+       public class TreeView : TemplatedGroup
+       {
+               Widget selectedItemContainer = null;
+               bool isRoot;
+
+               #region CTOR
+               protected TreeView() : base(){}
+               public TreeView (Interface iface) : base(iface)
+               {
+               }
+               #endregion
+
+               [DefaultValue(false)]
+               public virtual bool IsRoot {
+                       get { return isRoot; }
+                       set {
+                               if (isRoot == value)
+                                       return;
+                               isRoot = value;
+                               NotifyValueChanged ("IsRoot", isRoot);
+                       }
+               }
+               [XmlIgnore]public override object SelectedItem {
+                       get {
+                               return selectedItemContainer == null ?
+                                       "" : selectedItemContainer.DataSource;
+                       }
+               }
+
+               internal override void itemClick (object sender, MouseButtonEventArgs e)
+               {
+                       Widget tmp = sender as Widget;
+                       //if (!tmp.HasFocus)
+                       //      return;
+                       /*if (selectedItemContainer != null) {
+                               selectedItemContainer.Foreground = Color.Transparent;
+                               selectedItemContainer.Background = Color.Transparent;
+                       }*/
+                       selectedItemContainer = tmp;
+                       //selectedItemContainer.Foreground = SelectionForeground;
+                       //selectedItemContainer.Background = SelectionBackground;
+                       NotifyValueChanged ("SelectedItem", SelectedItem);
+                       raiseSelectedItemChanged ();
+               }
+
+               void onExpandAll_MouseClick (object sender, MouseButtonEventArgs e)
+               {
+                       ExpandAll ();
+               }
+
+               public void ExpandAll(){
+                       foreach (Group grp in items.Children) {
+                               foreach (Widget go in grp.Children) {
+                                       Expandable exp = go as Expandable;
+                                       if (exp == null)
+                                               continue;
+                                       TreeView subTV = exp.FindByName ("List") as TreeView;
+                                       if (subTV == null)
+                                               continue;
+                                       EventHandler handler = null;
+                                       handler = delegate(object sender, EventArgs e) {
+                                               TreeView tv = sender as TreeView;
+                                               tv.Loaded -= handler;
+                                               tv.ExpandAll ();
+                                       };
+                                       subTV.Loaded += handler;
+                                       exp.IsExpanded = true;
+                               }
+                       }
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/Trend.cs b/Crow/src/Widgets/Trend.cs
new file mode 100644 (file)
index 0000000..b62fd2f
--- /dev/null
@@ -0,0 +1,189 @@
+//
+// Trend.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.Collections.Generic;
+using System.Xml.Serialization;
+using System.ComponentModel;
+using Crow.Cairo;
+
+namespace Crow
+{
+       public class Trend : Widget
+       {
+               #region private fields
+               double minValue, maxValue, lowThreshold, highThreshold;
+               Fill lowThresholdFill, highThresholdFill;
+               int nbValues;
+               List<double> values = new List<double>();
+               #endregion
+
+
+
+               public virtual void AddValue(double _value)
+               {
+                       values.Add (_value);
+                       while (values.Count > nbValues)
+                               values.RemoveAt (0);
+                       RegisterForRedraw ();
+               }
+               #region CTOR
+               protected Trend () : base()
+               {
+               }
+               #endregion
+               [XmlIgnore]public virtual int NewValue {
+                       set {
+                               AddValue (value);
+                       }
+               }
+               [DefaultValue(400)]
+               public virtual int NbValues {
+                       get { return nbValues; }
+                       set {
+                               if (nbValues == value)
+                                       return;
+
+                               nbValues = value;
+                               NotifyValueChanged ("NbValues", minValue);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(0.0)]
+               public virtual double Minimum {
+                       get { return minValue; }
+                       set {
+                               if (minValue == value)
+                                       return;
+
+                               minValue = value;
+                               NotifyValueChanged ("Minimum", minValue);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(100.0)]
+               public virtual double Maximum
+               {
+                       get { return maxValue; }
+                       set {
+                               if (maxValue == value)
+                                       return;
+
+                               maxValue = value;
+                               NotifyValueChanged ("Maximum", maxValue);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(1.0)]
+               public virtual double LowThreshold {
+                       get { return lowThreshold; }
+                       set {
+                               if (lowThreshold == value)
+                                       return;
+                               lowThreshold = value;
+                               NotifyValueChanged ("LowThreshold", lowThreshold);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               [DefaultValue(80.0)]
+               public virtual double HighThreshold {
+                       get { return highThreshold; }
+                       set {
+                               if (highThreshold == value)
+                                       return;
+                               highThreshold = value;
+                               NotifyValueChanged ("HighThreshold", highThreshold);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               [DefaultValue("DarkRed")]
+               public virtual Fill LowThresholdFill {
+                       get { return lowThresholdFill; }
+                       set {
+                               if (lowThresholdFill == value)
+                                       return;
+                               lowThresholdFill = value;
+                               NotifyValueChanged ("LowThresholdFill", lowThresholdFill);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue("DarkGreen")]
+               public virtual Fill HighThresholdFill {
+                       get { return highThresholdFill; }
+                       set {
+                               if (highThresholdFill == value)
+                                       return;
+                               highThresholdFill = value;
+                               NotifyValueChanged ("HighThresholdFill", highThresholdFill);
+                               RegisterForRedraw ();
+                       }
+               }
+               protected override void onDraw (Context gr)
+               {
+                       base.onDraw (gr);
+
+                       if (values.Count == 0)
+                               return;
+                       Rectangle r = ClientRectangle;
+
+                       int i = values.Count -1;
+
+                       double ptrX = (double)r.Right;
+                       double scaleY = (double)r.Height / (Maximum - Minimum);
+                       double stepX = (double)r.Width / (double)(nbValues-1);
+
+                       gr.LineWidth = 1.0;
+                       gr.SetDash (new double[]{ 1.0 },0.0);
+
+
+
+                       LowThresholdFill.SetAsSource (gr);
+                       gr.MoveTo (r.Left, r.Bottom - LowThreshold * scaleY);
+                       gr.LineTo (r.Right, r.Bottom - LowThreshold * scaleY);
+//                     gr.Rectangle (r.Left, r.Bottom - LowThreshold * scaleY, r.Width, LowThreshold * scaleY);
+                       gr.Stroke();
+
+                       HighThresholdFill.SetAsSource (gr);
+                       gr.MoveTo (r.Left, (Maximum - HighThreshold) * scaleY);
+                       gr.LineTo (r.Right, (Maximum - HighThreshold) * scaleY);
+//                     gr.Rectangle (r.Left, r.Top, r.Width, (Maximum - HighThreshold) * scaleY);
+                       gr.Stroke();
+
+                       gr.MoveTo (ptrX, values [i] * scaleY);
+
+                       Foreground.SetAsSource (gr);
+                       gr.SetDash (new double[]{ }, 0.0);
+
+                       while (i >= 0) {
+                                       gr.LineTo (ptrX, r.Bottom - values [i] * scaleY);
+                               ptrX -= stepX;
+                               i--;
+                       }
+                       gr.Stroke ();
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/VerticalStack.cs b/Crow/src/Widgets/VerticalStack.cs
new file mode 100644 (file)
index 0000000..cf0a251
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// VerticalStack.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.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Crow
+{
+       /// <summary>
+       /// group control stacking its children vertically
+       /// </summary>
+    public class VerticalStack : GenericStack
+    {
+               #region CTOR
+               protected VerticalStack() : base(){}
+               public VerticalStack(Interface iface) : base(iface)
+        {
+        }
+               #endregion
+
+        [XmlIgnore]
+        public override Orientation Orientation
+        {
+            get { return Orientation.Vertical; }            
+        }
+
+
+    }
+}
diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs
new file mode 100644 (file)
index 0000000..d6c3a96
--- /dev/null
@@ -0,0 +1,2032 @@
+//
+// GraphicObject.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.Collections.Generic;
+using System.ComponentModel;
+using System.Xml.Serialization;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using Crow.Cairo;
+using System.Diagnostics;
+using Crow.IML;
+using System.Threading;
+
+
+#if DESIGN_MODE
+using System.Xml;
+using System.IO;
+#endif
+
+namespace Crow
+{
+       /// <summary>
+       /// The base class for all the graphic tree elements.
+       /// </summary>
+       public class Widget : ILayoutable, IValueChange, IDisposable
+       {
+               internal ReaderWriterLockSlim parentRWLock = new ReaderWriterLockSlim();
+               #if DEBUG_LOG
+               //0 is the main graphic tree, for other obj tree not added to main tree, it range from 1->n
+               //useful to track events for obj shown later, not on start, or never added to main tree
+               public int treeIndex;
+               public int yIndex;//absolute index in the graphic tree for debug draw
+               public int xLevel;//x increment for debug draw
+               #endif
+               #if DESIGN_MODE
+               static MethodInfo miDesignAddDefLoc = typeof(Widget).GetMethod("design_add_style_location",
+                       BindingFlags.Instance | BindingFlags.NonPublic);
+               static MethodInfo miDesignAddValLoc = typeof(Widget).GetMethod("design_add_iml_location",
+                       BindingFlags.Instance | BindingFlags.NonPublic);
+               
+               public volatile bool design_HasChanged = false;
+               public string design_id;
+               public int design_line;
+               public int design_column;
+               public string design_imlPath;
+               public bool design_isTGItem = false;//true if this is a templated item's root
+               public Dictionary<string,string> design_iml_values = new Dictionary<string, string>();
+               public Dictionary<string,string> design_style_values = new Dictionary<string, string>();
+               //public Dictionary<string,FileLocation> design_iml_locations = new Dictionary<string, FileLocation>();
+               public Dictionary<string,FileLocation> design_style_locations = new Dictionary<string, FileLocation>();
+
+               internal void design_add_style_location (string memberName, string path, int line, int col) {                   
+                       if (design_style_locations.ContainsKey(memberName)){
+                               Console.WriteLine ("default value localtion already set for {0}{1}.{2}", this.GetType().Name, this.design_id, memberName);
+                               return;
+                       }
+                       design_style_locations.Add(memberName, new FileLocation(path,line,col));
+               }
+//             internal void design_add_iml_location (string memberName, string path, int line, int col) {
+//                     if (design_iml_locations.ContainsKey(memberName)){
+//                             Console.WriteLine ("IML value localtion already set for {0}{1}.{2}", this.GetType().Name, this.design_id, memberName);
+//                             return;
+//                     }
+//                     design_iml_locations.Add(memberName, new FileLocation(path,line,col));
+//             }
+                       
+               public virtual bool FindByDesignID(string designID, out Widget go){
+                       go = null;
+                       if (this.design_id == designID){
+                               go = this;
+                               return true;
+                       }
+                       return false;
+               }
+
+               public string GetIML(){
+                       XmlDocument doc = new XmlDocument( );
+
+                       using (StringWriter sw = new StringWriter ()) {
+                               XmlWriterSettings settings = new XmlWriterSettings {
+                                       Indent = true,
+                                       IndentChars = "\t",
+                               };
+                               using (XmlWriter xtw = XmlWriter.Create (sw, settings)) {
+                                       //(1) the xml declaration is recommended, but not mandatory
+                                       XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration ("1.0", "UTF-8", null);
+                                       doc.InsertBefore (xmlDeclaration, null);
+                                       getIML (doc, (XmlNode)doc);
+                                       doc.WriteTo (xtw);
+                               }
+                               this.design_HasChanged = false;
+                               return sw.ToString ();
+                       }
+               }
+
+               public virtual void getIML(XmlDocument doc, XmlNode parentElem) {
+                       if (this.design_isTGItem)
+                               return;
+                       
+                       XmlElement xe = doc.CreateElement(this.GetType().Name);
+
+                       foreach (KeyValuePair<string,string> kv in design_iml_values) {
+                               XmlAttribute xa = doc.CreateAttribute (kv.Key);
+                               xa.Value = kv.Value;
+                               xe.Attributes.Append (xa);
+                       }
+
+                       parentElem.AppendChild (xe);
+               }
+               public Surface CreateIcon (int dragIconSize = 32) {
+                       ImageSurface di = new ImageSurface (Format.Argb32, dragIconSize, dragIconSize);
+                       using (Context ctx = new Context (di)) {
+                               double div = Math.Max (LastPaintedSlot.Width, LastPaintedSlot.Height);
+                               double s = (double)dragIconSize / div;
+                               ctx.Scale (s, s);
+                               if (bmp == null)
+                                       this.onDraw (ctx);
+                               else {
+                                       if (LastPaintedSlot.Width>LastPaintedSlot.Height)
+                                               ctx.SetSourceSurface (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2);
+                                       else
+                                               ctx.SetSourceSurface (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0);
+                                       ctx.Paint ();
+                               }
+                       }
+                       return di;
+               }
+        public string DesignName {
+            get { return GetType ().Name + design_id; }
+        }
+               #endif
+
+               #region IDisposable implementation
+               protected bool disposed = false;
+
+               public void Dispose(){  
+                       Dispose(true);  
+                       GC.SuppressFinalize(this);  
+               }  
+               ~Widget(){
+                       Console.WriteLine(this.ToString() + " not disposed by user");
+                       Dispose(false);
+               }
+               protected virtual void Dispose(bool disposing){
+                       if (disposed){
+                               #if DEBUG_DISPOSE
+                               Console.WriteLine ("Trying to dispose already disposed obj: {0}", this.ToString());
+                               #endif
+                               return;
+                       }
+
+                       if (disposing) {
+                               #if DEBUG_DISPOSE
+                               Console.WriteLine ("Disposing: {0}", this.ToString());
+                               //if ()
+                               //throw new Exception("Trying to dispose an object queued for Redraw: " + this.ToString());
+                               #endif
+
+                               unshownPostActions ();
+
+                               if (!localDataSourceIsNull)
+                                       DataSource = null;
+
+                               parentRWLock.EnterWriteLock();
+                               parent = null;
+                               parentRWLock.ExitWriteLock();
+                       } else
+                               Debug.WriteLine ("!!! Finalized by GC: {0}", this.ToString ());
+                       Clipping?.Dispose ();
+                       bmp?.Dispose ();
+                       disposed = true;
+               }  
+               #endregion
+
+               #if DEBUG_LOG
+               internal static List<GraphicObject> GraphicObjects = new List<GraphicObject>();
+               #endif
+
+               //internal bool isPopup = false;
+               //public Widget focusParent {
+               //      get { return (isPopup ? LogicalParent : parent) as Widget; }
+               //}
+
+               /// <summary>
+               /// interface this widget is bound to, this should not be changed once the instance is created
+               /// </summary>
+               public Interface IFace = null;
+
+               /// <summary>
+               /// contains the dirty rectangles in the coordinate system of the cache. those dirty zones
+               /// are repeated at each cached levels of the tree with correspondig coordinate system. This is done
+               /// in a dedicated step of the update between layouting and drawing.
+               /// </summary>
+               public Region Clipping;
+
+               #region IValueChange implementation
+               /// <summary>
+               /// Raise to notify that the value of a property has changed, the binding system
+               /// rely mainly on this event. the member name may not be present in the class, this is 
+               /// used in **propertyless** bindings, this allow to raise custom named events without needing
+               /// to create an new one in the class or a new property.
+               /// </summary>
+               public event EventHandler<ValueChangeEventArgs> ValueChanged;
+               /// <summary>
+               /// Helper function to raise the value changed event
+               /// </summary>
+               public virtual void NotifyValueChanged(string MemberName, object _value)
+               {
+                       //Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value);
+                       ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value));
+               }
+               #endregion
+
+               #region CTOR
+               /// <summary>
+               /// default private parameter less constructor use in instantiators, it should not be used
+               /// when creating widget from code because widgets has to be bound to an interface before any other
+               /// action.
+               /// </summary>
+               protected Widget () {
+                       Clipping = new Region ();
+                       #if DEBUG_LOG
+                       GraphicObjects.Add (this);
+                       DebugLog.AddEvent(DbgEvtType.GOClassCreation, this);
+                       #endif                  
+               }
+               /// <summary>
+               /// This constructor **must** be used when creating widget from code.
+               ///
+               /// When creating new widgets derived from GraphicObject, both parameterless and this constructors are
+               /// facultatives, the compiler will create the parameterless one automaticaly if no other one exists.
+               /// But if you intend to be able to create instances of the new widget in code and override the constructor
+               /// with the Interface parameter, you **must** also provide the override of the parameterless constructor because
+               /// compiler will not create it automatically because of the presence of the other one.
+               /// </summary>
+               /// <param name="iface">Iface.</param>
+               public Widget (Interface iface) : this()
+               {
+                       IFace = iface;
+                       Initialize ();
+               }
+               #endregion
+               //internal bool initialized = false;
+               /// <summary>
+               /// Initialize this Graphic object instance by setting style and default values and loading template if required
+               /// </summary>
+               public virtual void Initialize(){
+                       loadDefaultValues ();
+               }
+               #region private fields
+               LayoutingType registeredLayoutings = LayoutingType.All;
+               ILayoutable logicalParent;
+               ILayoutable parent;
+               string name;
+               Fill background = Color.Transparent;
+               Fill foreground = Color.White;
+               Font font = "sans, 10";
+               protected Measure width, height;
+               int left, top;
+               double cornerRadius;
+               int margin;
+               bool focusable ;
+               bool hasFocus;
+               bool isActive;
+               bool isHover;
+               bool mouseRepeat;
+               MouseCursor mouseCursor = MouseCursor.Arrow;
+               protected bool isVisible = true;
+               bool isEnabled = true;
+               VerticalAlignment verticalAlignment = VerticalAlignment.Center;
+               HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center;
+               Size maximumSize = "0,0";
+               Size minimumSize = "0,0";
+               bool cacheEnabled;
+               bool clipToClientRect = true;
+               Type dataSourceType;
+               protected object dataSource;
+               bool rootDataLevel;
+               string style;
+               object tag;
+               bool isDragged;
+               bool allowDrag;
+               bool allowDrop;
+               string tooltip;
+               IList<Command> contextCommands;
+               #endregion
+
+               #region public fields
+               /// <summary>
+               /// Current size and position computed during layouting pass
+               /// </summary>
+               public Rectangle Slot = new Rectangle ();
+               /// <summary>
+               /// keep last slot components for each layouting pass to track
+               /// changes and trigger update of other component accordingly
+               /// </summary>
+               public Rectangle LastSlots;
+               /// <summary>
+               /// keep last slot painted on screen to clear traces if moved or resized
+               /// 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 IsQueueForClipping = false;
+               /// <summary>drawing Cache, if null, a redraw is done, cached or not</summary>
+               public Surface bmp;
+               public bool IsDirty = true;
+               /// <summary>
+               /// This size is computed on each child' layout changes.
+               /// In stacking widget, it is used to compute the remaining space for the stretched
+               /// widget inside the stack, which is never added to the contentSize, instead, its size
+               /// is deducted from (parent.ClientRectangle - contentSize)
+               /// </summary>
+               internal Size contentSize;
+               #endregion
+
+               #region ILayoutable
+               [XmlIgnore]public LayoutingType RegisteredLayoutings { get { return registeredLayoutings; } set { registeredLayoutings = value; } }
+               //TODO: it would save the recurent cost of a cast in event bubbling if parent type was GraphicObject
+               //              or we could add to the interface the mouse events
+               /// <summary>
+               /// Parent in the graphic tree, used for rendering and layouting
+               /// </summary>
+               [XmlIgnore]public virtual ILayoutable Parent {
+                       get { return parent; }
+                       set {
+                               if (parent == value)
+                                       return;
+                               DataSourceChangeEventArgs e = new DataSourceChangeEventArgs (parent, value);
+
+                               parentRWLock.EnterWriteLock();
+                               parent = value;
+                               Slot = LastSlots = default(Rectangle);
+                               parentRWLock.ExitWriteLock();
+                                                                       
+                               onParentChanged (this, e);
+                       }
+               }
+               /// <summary>
+               /// Mouse routing need to go back to logical parent for popups
+               /// </summary>
+               public Widget FocusParent => (parent is Interface ? LogicalParent : parent) as Widget; 
+
+               [XmlIgnore]public ILayoutable LogicalParent {
+                       get { return logicalParent == null ? Parent : logicalParent; }
+                       set {
+                               if (logicalParent == value)
+                                       return;
+                               if (logicalParent is Widget)
+                                       (logicalParent as Widget).DataSourceChanged -= onLogicalParentDataSourceChanged;
+                               DataSourceChangeEventArgs dsce = new DataSourceChangeEventArgs (LogicalParent, null);
+                               logicalParent = value;
+                               dsce.NewDataSource = LogicalParent;
+                               if (logicalParent is Widget)
+                                       (logicalParent as Widget).DataSourceChanged += onLogicalParentDataSourceChanged;
+                               onLogicalParentChanged (this, dsce);
+                       }
+               }
+               [XmlIgnore]public virtual Rectangle ClientRectangle {
+                       get {
+                               Rectangle cb = Slot.Size;
+                               cb.Inflate ( - margin);
+                               return cb;
+                       }
+               }
+               public virtual Rectangle ContextCoordinates(Rectangle r){
+                       Widget go = Parent as Widget;
+                       if (go == null)
+                               return r + Parent.ClientRectangle.Position;
+                       return go.CacheEnabled ?
+                               r + Parent.ClientRectangle.Position :
+                               Parent.ContextCoordinates (r);
+               }
+               public virtual Rectangle ScreenCoordinates (Rectangle r){
+                       try {
+                               return
+                                       Parent.ScreenCoordinates(r) + Parent.getSlot().Position + Parent.ClientRectangle.Position;                              
+                       } catch (Exception ex) {
+                               Debug.WriteLine (ex);
+                               return default(Rectangle);
+                       }
+               }
+               public virtual Rectangle getSlot () { return Slot;}
+               #endregion
+               public Point ScreenPointToLocal(Point p){
+                       Point pt = p - ScreenCoordinates (Slot).TopLeft - ClientRectangle.TopLeft;
+                       if (pt.X < 0)
+                               pt.X = 0;
+                       if (pt.Y < 0)
+                               pt.Y = 0;
+                       return pt;
+               }
+
+               #region EVENT HANDLERS
+               /// <summary>Occurs when mouse wheel is rolled in this object. It bubbles to the root</summary>
+               public event EventHandler<MouseWheelEventArgs> MouseWheelChanged;
+               /// <summary>Occurs when mouse button is released in this object. It bubbles to the root</summary>
+               public event EventHandler<MouseButtonEventArgs> MouseUp;
+               /// <summary>Occurs when mouse button is pressed in this object. It bubbles to the root</summary>
+               public event EventHandler<MouseButtonEventArgs> MouseDown;
+               /// <summary>Occurs when mouse button has been pressed then relesed in this object. It bubbles to the root</summary>
+               public event EventHandler<MouseButtonEventArgs> MouseClick;
+               /// <summary>Occurs when mouse button has been pressed then relesed 2 times in this object. It bubbles to the root</summary>
+               public event EventHandler<MouseButtonEventArgs> MouseDoubleClick;
+               /// <summary>Occurs when mouse mouve in this object. It bubbles to the root</summary>
+               public event EventHandler<MouseMoveEventArgs> MouseMove;
+               /// <summary>Occurs when mouse enter this object</summary>
+               public event EventHandler<MouseMoveEventArgs> MouseEnter;
+               /// <summary>Occurs when mouse leave this object</summary>
+               public event EventHandler<MouseMoveEventArgs> MouseLeave;
+               /// <summary>Occurs when key is pressed when this object is active</summary>
+               public event EventHandler<KeyEventArgs> KeyDown;
+               /// <summary>Occurs when key is released when this object is active</summary>
+               public event EventHandler<KeyEventArgs> KeyUp;
+               /// <summary>Occurs when translated key event occurs in the host when this object is active</summary>
+               public event EventHandler<KeyPressEventArgs> KeyPress;
+               /// <summary>Occurs when this object received focus</summary>
+               public event EventHandler Focused;
+               /// <summary>Occurs when this object loose focus</summary>
+               public event EventHandler Unfocused;
+               /// <summary>Occurs when mouse is over</summary>
+               public event EventHandler Hover;
+               /// <summary>Occurs when this control is no longer the Hover one</summary>
+               //public event EventHandler UnHover;
+               /// <summary>Occurs when this object loose focus</summary>
+               public event EventHandler Enabled;
+               /// <summary>Occurs when the enabled state this object is set to false</summary>
+               public event EventHandler Disabled;
+
+               #region DragAndDrop Events
+               public event EventHandler<DragDropEventArgs> StartDrag;
+               public event EventHandler<DragDropEventArgs> DragEnter;
+               public event EventHandler<DragDropEventArgs> DragLeave;
+               public event EventHandler<DragDropEventArgs> EndDrag;
+               public event EventHandler<DragDropEventArgs> Drop;
+               #endregion
+
+               /// <summary>
+               /// Occurs when default value and styling are loaded, and for templated control,
+               /// template is also loaded. Bindings should be functionnal as well.
+               /// </summary>
+               public event EventHandler Initialized;
+
+               /// <summary>Occurs when one part of the rendering slot changed</summary>
+               public event EventHandler<LayoutingEventArgs> LayoutChanged;
+               /// <summary>Occurs when DataSource changed</summary>
+               public event EventHandler<DataSourceChangeEventArgs> DataSourceChanged;
+               /// <summary>Occurs when the parent has changed</summary>
+               public event EventHandler<DataSourceChangeEventArgs> ParentChanged;
+               /// <summary>Occurs when the logical parent has changed</summary>
+               public event EventHandler<DataSourceChangeEventArgs> LogicalParentChanged;
+               #endregion
+
+               internal bool hasDoubleClick => MouseDoubleClick != null;
+               internal bool hasClick => MouseClick != null;
+
+               #region public properties
+               /// <summary>Random value placeholder</summary>
+               [DesignCategory ("Divers")]
+               public object Tag {
+                       get { return tag; }
+                       set {
+                               if (tag == value)
+                                       return;
+                               tag = value;
+                               NotifyValueChanged ("Tag", tag);
+                       }
+               }
+               /// <summary>
+               /// If enabled, resulting bitmap of graphic object is cached
+               /// speeding up rendering of complex object. Default is enabled.
+               /// </summary>
+               [DesignCategory ("Behavior")][DefaultValue(true)]
+               public virtual bool CacheEnabled {
+                       get { return cacheEnabled; }
+                       set {
+                               if (cacheEnabled == value)
+                                       return;
+                               cacheEnabled = value;
+                               NotifyValueChanged ("CacheEnabled", cacheEnabled);
+                       }
+               }
+               /// <summary>
+               /// If true, rendering of GraphicObject is clipped inside client rectangle
+               /// </summary>
+               [DesignCategory ("Appearance")][DefaultValue(true)]
+               public virtual bool ClipToClientRect {
+                       get { return clipToClientRect; }
+                       set {
+                               if (clipToClientRect == value)
+                                       return;
+                               clipToClientRect = value;
+                               NotifyValueChanged ("ClipToClientRect", clipToClientRect);
+                               this.RegisterForRedraw ();
+                       }
+               }
+               #if DEBUG_LOG
+               [XmlIgnore]public string TreePath {
+                       get { return this.GetType().Name + GraphicObjects.IndexOf(this).ToString ();    }
+               }
+               #endif
+               /// <summary>
+               /// Name is used in binding to reference other GraphicObjects inside the graphic tree
+               /// and by template controls to find special element in their template implementation such
+               /// as a container or a group to put children in.
+               /// </summary>
+               [DesignCategory ("Divers")][DefaultValue(null)]
+               public virtual string Name {
+                       get {
+                               #if DEBUG_LOG
+                               return string.IsNullOrEmpty(name) ? this.GetType().Name + GraphicObjects.IndexOf(this).ToString () : name;
+                               #else
+                               return name;
+                               #endif
+                       }
+                       set {
+                               if (name == value)
+                                       return;
+                               name = value;
+                               NotifyValueChanged("Name", name);
+                       }
+               }
+               /// <summary>
+               /// Vertical alignment inside parent, disabled if height is stretched
+               /// or top coordinate is not null
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue(VerticalAlignment.Center)]
+               public virtual VerticalAlignment VerticalAlignment {
+                       get { return verticalAlignment; }
+                       set {
+                               if (verticalAlignment == value)
+                                       return;
+
+                               verticalAlignment = value;
+                               NotifyValueChanged("VerticalAlignment", verticalAlignment);
+                               RegisterForLayouting (LayoutingType.Y);
+                       }
+               }
+               /// <summary>
+               /// Horizontal alignment inside parent, disabled if width is stretched
+               /// or left coordinate is not null
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue(HorizontalAlignment.Center)]
+               public virtual HorizontalAlignment HorizontalAlignment {
+                       get { return horizontalAlignment; }
+                       set {
+                               if (horizontalAlignment == value)
+                                       return;
+                               horizontalAlignment = value;
+                               NotifyValueChanged("HorizontalAlignment", horizontalAlignment);
+                               RegisterForLayouting (LayoutingType.X);
+                       }
+               }
+               /// <summary>
+               /// x position inside parent
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue(0)]
+               public virtual int Left {
+                       get { return left; }
+                       set {
+                               if (left == value)
+                                       return;
+                               left = value;
+                               NotifyValueChanged ("Left", left);
+                               this.RegisterForLayouting (LayoutingType.X);
+                       }
+               }
+               /// <summary>
+               /// y position inside parent
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue(0)]
+               public virtual int Top {
+                       get { return top; }
+                       set {
+                               if (top == value)
+                                       return;
+                               top = value;
+                               NotifyValueChanged ("Top", top);
+                               this.RegisterForLayouting (LayoutingType.Y);
+                       }
+               }
+               /// <summary>
+               /// Helper property used to set width and height to fit in one call
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue(false)]
+               public virtual bool Fit {
+                       get { return Width == Measure.Fit && Height == Measure.Fit ? true : false; }
+                       set {
+                               if (value == Fit)
+                                       return;
+
+                               Width = Height = Measure.Fit;
+                       }
+               }
+               /// <summary>
+               /// Width of this control, by default inherited from parent. May have special values
+               /// such as Stretched or Fit. It may be proportionnal or absolute.
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue("Inherit")]
+               public virtual Measure Width {
+                       get {
+                               return width.Units == Unit.Inherit ?
+                                       Parent is Widget ? (Parent as Widget).WidthPolicy :
+                                       Measure.Stretched : width;
+                       }
+                       set {
+                               if (width == value)
+                                       return;
+                               if (value.IsFixed) {
+                                       if (value < minimumSize.Width || (value > maximumSize.Width && maximumSize.Width > 0))
+                                               return;
+                               }
+                               Measure old = width;
+                               width = value;
+                               NotifyValueChanged ("Width", width);
+                               if (width == Measure.Stretched || old == Measure.Stretched) {
+                                       //NotifyValueChanged ("WidthPolicy", width.Policy);
+                                       //contentSize in Stacks are only update on childLayoutChange, and the single stretched
+                                       //child of the stack is not counted in contentSize, so when changing size policy of a child
+                                       //we should adapt contentSize
+                                       //TODO:check case when child become stretched, and another stretched item already exists.
+                                       GenericStack gs = Parent as GenericStack;
+                                       if (gs != null){ //TODO:check if I should test Group instead
+                                               if (gs.Orientation == Orientation.Horizontal) {
+                                                       if (width == Measure.Stretched)
+                                                               gs.contentSize.Width -= this.LastSlots.Width;
+                                                       else
+                                                               gs.contentSize.Width += this.LastSlots.Width;
+                                               }
+                                       }                                                       
+                               }
+
+                               this.RegisterForLayouting (LayoutingType.Width);
+                       }
+               }
+               /// <summary>
+               /// Height of this control, by default inherited from parent. May have special values
+               /// such as Stretched or Fit. It may be proportionnal or absolute.
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue("Inherit")]
+               public virtual Measure Height {
+                       get {
+                               return height.Units == Unit.Inherit ?
+                                       Parent is Widget ? (Parent as Widget).HeightPolicy :
+                                       Measure.Stretched : height;
+                       }
+                       set {
+                               if (height == value)
+                                       return;
+                               if (value.IsFixed) {
+                                       if (value < minimumSize.Height || (value > maximumSize.Height && maximumSize.Height > 0))
+                                               return;
+                               }
+                               Measure old = height;
+                               height = value;
+                               NotifyValueChanged ("Height", height);
+                               if (height == Measure.Stretched || old == Measure.Stretched) {
+                                       //NotifyValueChanged ("HeightPolicy", HeightPolicy);
+                                       GenericStack gs = Parent as GenericStack;
+                                       if (gs != null){ //TODO:check if I should test Group instead
+                                               if (gs.Orientation == Orientation.Vertical) {
+                                                       if (height == Measure.Stretched)
+                                                               gs.contentSize.Height -= this.LastSlots.Height;
+                                                       else
+                                                               gs.contentSize.Height += this.LastSlots.Height;
+                                               }
+                                       }
+                               }
+
+                               this.RegisterForLayouting (LayoutingType.Height);
+                       }
+               }
+               /// <summary>
+               /// Was Used for binding on dimensions, this property will never hold fixed size, but instead only
+               /// Fit or Stretched, **with inherited state implementation, it is not longer used in binding**
+               /// </summary>
+               [XmlIgnore]public virtual Measure WidthPolicy { get {
+                               return Width.IsFit ? Measure.Fit : Measure.Stretched; } }
+               /// <summary>
+               /// Was Used for binding on dimensions, this property will never hold fixed size, but instead only
+               /// Fit or Stretched, **with inherited state implementation, it is not longer used in binding**
+               /// </summary>
+               [XmlIgnore]public virtual Measure HeightPolicy { get {
+                               return Height.IsFit ? Measure.Fit : Measure.Stretched; } }
+               /// <summary>
+               /// Indicate that this object may received focus or not, if not focusable all the descendants are 
+               /// affected.
+               /// </summary>
+               [DesignCategory ("Behaviour")][DefaultValue(false)]
+               public virtual bool Focusable {
+                       get { return focusable; }
+                       set {
+                               if (focusable == value)
+                                       return;
+                               focusable = value;
+                               NotifyValueChanged ("Focusable", focusable);
+                       }
+               }
+               /// <summary>
+               /// True when this control has the focus, only one control per interface may have it.
+               /// </summary>
+               [XmlIgnore]public virtual bool HasFocus {
+                       get { return hasFocus; }
+                       set {
+                               if (value == hasFocus)
+                                       return;
+
+                               hasFocus = value;
+                               if (hasFocus)
+                                       onFocused (this, null);
+                               else
+                                       onUnfocused (this, null);
+                               NotifyValueChanged ("HasFocus", hasFocus);
+                       }
+               }
+               /// <summary>
+               /// true if this control is active, this means that mouse has been pressed in it and not yet released. It could 
+               /// be used for other two states periferic action.
+               /// </summary>
+               [XmlIgnore]public virtual bool IsActive {
+                       get { return isActive; }
+                       set {
+                               if (value == isActive)
+                                       return;
+
+                               isActive = value;
+                               NotifyValueChanged ("IsActive", isActive);
+                       }
+               }
+               /// <summary>
+               /// true if this control has the pointer hover
+               /// </summary>
+               [XmlIgnore]public virtual bool IsHover {
+                       get { return isHover; }
+                       set {
+                               if (value == isHover)
+                                       return;
+
+                               isHover = value;
+
+                               if (isHover)
+                                       Hover.Raise (this, null);
+
+                               NotifyValueChanged ("IsHover", isHover);
+                       }
+               }
+               /// <summary>
+               /// true if holding mouse button down should trigger multiple click events
+               /// </summary>
+               [DesignCategory ("Behaviour")][DefaultValue(false)]
+               public virtual bool MouseRepeat {
+                       get { return mouseRepeat; }
+                       set {
+                               if (mouseRepeat == value)
+                                       return;
+                               mouseRepeat = value;
+                               NotifyValueChanged ("MouseRepeat", mouseRepeat);
+                       }
+               }
+               /// <summary>
+               /// Determine Cursor when mouse is Hover.
+               /// </summary>
+               [DesignCategory ("Behaviour")]
+               [DefaultValue (MouseCursor.Arrow)]
+               public virtual MouseCursor MouseCursor {
+                       get { return mouseCursor; }
+                       set {
+                               if (mouseCursor == value)
+                                       return;
+                               mouseCursor = value;
+                               NotifyValueChanged ("MouseCursor", mouseCursor);
+                               this.RegisterForRedraw ();
+
+                               if (isHover)
+                                       IFace.MouseCursor = mouseCursor;
+                       }
+               }
+
+               /// <summary>
+               /// forward mouse events even if an handle is bound
+               /// </summary>
+               //[DesignCategory ("Behaviour")][DefaultValue (false)]
+               //public bool ForwardMouseEvents {
+               //      get { return forwardMouseEvents; }
+               //      set {
+               //              if (forwardMouseEvents == value)
+               //                      return;
+               //              forwardMouseEvents = value;
+               //              NotifyValueChanged ("ForwardMouseEvents", forwardMouseEvents);
+               //      }
+               //}
+               bool clearBackground = false;
+               /// <summary>
+               /// background fill of the control, maybe solid color, gradient, image, or svg
+               /// </summary>
+               [DesignCategory ("Appearance")][DefaultValue("Transparent")]
+               public virtual Fill Background {
+                       get { return background; }
+                       set {
+                               if (background == value)
+                                       return;
+                               clearBackground = false;
+                               if (value == null)
+                                       return;
+                               background = value;
+                               NotifyValueChanged ("Background", background);
+                               RegisterForRedraw ();
+                               if (background is SolidColor) {
+                                       if ((background as SolidColor).Equals (Color.Clear))
+                                               clearBackground = true;
+                               }
+                       }
+               }
+               /// <summary>
+               /// Foreground fill of the control, usage may be different among derived controls
+               /// </summary>
+               [DesignCategory ("Appearance")][DefaultValue("White")]
+               public virtual Fill Foreground {
+                       get { return foreground; }
+                       set {
+                               if (foreground == value)
+                                       return;
+                               foreground = value;
+                               NotifyValueChanged ("Foreground", foreground);
+                               RegisterForRedraw ();
+                       }
+               }
+               /// <summary>
+               /// Font being used in many controls, it is defined in the base GraphicObject class.
+               /// </summary>
+               [DesignCategory ("Appearance")][DefaultValue("sans, 10")]
+               public virtual Font Font {
+                       get { return font; }
+                       set {
+                               if (value == font)
+                                       return;
+                               font = value;
+                               NotifyValueChanged ("Font", font);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary>
+               /// to get rounded corners
+               /// </summary>
+               [DesignCategory ("Appearance")][DefaultValue(0.0)]
+               public virtual double CornerRadius {
+                       get { return cornerRadius; }
+                       set {
+                               if (value == cornerRadius)
+                                       return;
+                               cornerRadius = value;
+                               NotifyValueChanged ("CornerRadius", cornerRadius);
+                               RegisterForRedraw ();
+                       }
+               }
+               /// <summary>
+               /// This is a single integer for the 4 direction, a gap between the control and it's container,
+               /// by default it is filled with the background.
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue(0)]
+               public virtual int Margin {
+                       get { return margin; }
+                       set {
+                               if (value == margin)
+                                       return;
+                               margin = value;
+                               NotifyValueChanged ("Margin", margin);
+                               RegisterForGraphicUpdate ();
+                       }
+               }
+               /// <summary>
+               /// set the visible state of the control, invisible controls does reserve space in the layouting system.
+               /// </summary>
+               [DesignCategory ("Appearance")][DefaultValue(true)]
+               public virtual bool Visible {
+                       get { return isVisible; }
+                       set {
+                               if (value == isVisible)
+                                       return;
+
+                               isVisible = value;
+
+                               RegisterForLayouting (LayoutingType.Sizing);
+
+                               if (!isVisible && IFace.HoverWidget != null) {                                  
+                                       if (IFace.HoverWidget.IsOrIsInside (this)) {
+                                               //IFace.HoverWidget = null;
+                                               IFace.OnMouseMove (IFace.Mouse.X, IFace.Mouse.Y);
+                                       }
+                               }
+
+                               NotifyValueChanged ("Visible", isVisible);
+                       }
+               }
+               /// <summary>
+               /// get or set the enabled state, disabling a control will affect focuability and
+               /// also it's rendering which will be grayed
+               /// </summary>
+               [DesignCategory ("Behaviour")][DefaultValue(true)]
+               public virtual bool IsEnabled {
+                       get { return isEnabled; }
+                       set {
+                               if (value == isEnabled)
+                                       return;
+
+                               isEnabled = value;
+
+                               if (isEnabled)
+                                       onEnable (this, null);
+                               else
+                                       onDisable (this, null);
+
+                               NotifyValueChanged ("IsEnabled", isEnabled);
+                               RegisterForRedraw ();
+                       }
+               }
+               /// <summary>
+               /// Minimal width and  height for this control
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue("1,1")]
+               public virtual Size MinimumSize {
+                       get { return minimumSize; }
+                       set {
+                               if (value == minimumSize)
+                                       return;
+
+                               minimumSize = value;
+
+                               NotifyValueChanged ("MinimumSize", minimumSize);
+                               RegisterForLayouting (LayoutingType.Sizing);
+                       }
+               }
+               /// <summary>
+               /// Maximum width and  height for this control, unlimited if null.
+               /// </summary>
+               [DesignCategory ("Layout")][DefaultValue("0,0")]
+               public virtual Size MaximumSize {
+                       get { return maximumSize; }
+                       set {
+                               if (value == maximumSize)
+                                       return;
+
+                               maximumSize = value;
+
+                               NotifyValueChanged (nameof(MaximumSize), maximumSize);
+                               RegisterForLayouting (LayoutingType.Sizing);
+                       }
+               }
+               /// <summary>
+               /// Fully qualify type name of expected data source.
+               /// If set, datasource bindings will be speedup by avoiding reflexion in generated dyn methods.
+               /// If an object of a different type is set as datasource, bindings will be canceled.
+               /// It accepts all derived type.
+               /// </summary>
+               [DesignCategory ("Data")]
+               public Type DataSourceType {
+                       get { return dataSourceType; }
+                       set { dataSourceType = value; }
+               }
+               /// <summary>
+               /// Seek first logical tree upward if logicalParent is set, or seek graphic tree for
+               /// a not null dataSource that will be active for all descendants having dataSource=null
+               /// </summary>
+               [DesignCategory ("Data")]
+               public virtual object DataSource {
+                       set {
+                               if (DataSource == value)
+                                       return;
+
+                               DataSourceChangeEventArgs dse = new DataSourceChangeEventArgs (DataSource, null);
+                               dataSource = value;
+                               dse.NewDataSource = DataSource;
+
+                               if (dse.NewDataSource == dse.OldDataSource)
+                                       return;
+
+                               if (value != null)
+                                       rootDataLevel = true;
+
+                               #if DEBUG_LOG
+                               DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOLockLayouting, this);
+                               #endif
+                               lock (IFace.UpdateMutex) {
+                                       OnDataSourceChanged (this, dse);
+                                       NotifyValueChanged ("DataSource", DataSource);
+                               }
+                               #if DEBUG_LOG
+                               dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+                               #endif
+                       }
+                       get {
+                               return rootDataLevel ? dataSource : dataSource == null ?
+                                       LogicalParent == null ? null :
+                                       LogicalParent is Widget ? (LogicalParent as Widget).DataSource : null :
+                                       dataSource;
+                       }
+               }
+               /// <summary>
+               /// If true, lock datasource seeking upward in logic or graphic tree to this widget
+               /// </summary>
+               [DesignCategory ("Data")][DefaultValue(false)]
+               public virtual bool RootDataLevel {
+                       get { return rootDataLevel; }
+                       set {
+                               if (rootDataLevel == value)
+                                       return;
+                               rootDataLevel = value;
+                               NotifyValueChanged ("RootDataLevel", rootDataLevel);
+                               this.RegisterForRedraw ();
+                       }
+               }
+               protected virtual void onLogicalParentDataSourceChanged(object sender, DataSourceChangeEventArgs e){
+                       if (localDataSourceIsNull)
+                               OnDataSourceChanged (this, e);
+               }
+               internal bool localDataSourceIsNull { get { return dataSource == null; } }
+               public bool localLogicalParentIsNull { get { return logicalParent == null; } }
+
+               public virtual void OnDataSourceChanged(object sender, DataSourceChangeEventArgs e){
+                       DataSourceChanged.Raise (this, e);
+                       #if DEBUG_LOG
+                       DebugLog.AddEvent(DbgEvtType.GONewDataSource, this);
+                       #endif
+
+                       #if DEBUG_BINDING
+                       Debug.WriteLine("New DataSource for => {0} \n\t{1}=>{2}", this.ToString(),e.OldDataSource,e.NewDataSource);
+                       #endif
+               }
+               /// <summary>
+               /// Style key to use for this control
+               /// </summary>
+               [DesignCategory ("Appearance")]
+               public virtual string Style {
+                       get { return style; }
+                       set {
+                               if (value == style)
+                                       return;
+
+                               style = value;
+
+                               NotifyValueChanged ("Style", style);
+                       }
+               }
+               [DesignCategory ("Divers")]
+               public virtual string Tooltip {
+                       get { return tooltip; }
+                       set {
+                               if (tooltip == value)
+                                       return;
+                               tooltip = value;
+                               NotifyValueChanged("Tooltip", tooltip);
+                       }
+               }
+               [DesignCategory ("Divers")]
+               public IList<Command> ContextCommands {
+                       get { return contextCommands; }
+                       set {
+                               if (contextCommands == value)
+                                       return;
+                               contextCommands = value;
+                               NotifyValueChanged("ContextCommands", contextCommands);
+                       }
+               }
+               #endregion
+
+               #region Default and Style Values loading
+               /// <summary> Loads the default values from XML attributes default </summary>
+               public void loadDefaultValues()
+               {
+                       #if DEBUG_LOG
+                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOInitialization, this);
+                       #endif
+
+                       Type thisType = this.GetType ();
+
+                       if (!string.IsNullOrEmpty (style)) {
+                               if (IFace.DefaultValuesLoader.ContainsKey (style)) {
+                                       IFace.DefaultValuesLoader [style] (this);
+                                       onInitialized (this, null);
+                                       return;
+                               }
+                       } else if (IFace.DefaultValuesLoader.ContainsKey (thisType.FullName)) {
+                               IFace.DefaultValuesLoader [thisType.FullName] (this);
+                               onInitialized (this, null);
+                               return;
+                       } else  if (IFace.DefaultValuesLoader.ContainsKey (thisType.Name)) {
+                               IFace.DefaultValuesLoader [thisType.Name] (this);
+                               onInitialized (this, null);
+                               return;
+                       }
+
+                       List<Style> styling = new List<Style>();
+
+                       //Search for a style matching :
+                       //1: Full class name, with full namespace
+                       //2: class name
+                       //3: style may have been registered with their ressource ID minus .style extention
+                       //   those files being placed in a Styles folder
+                       string styleKey = style;
+                       if (!string.IsNullOrEmpty (style)) {
+                               if (IFace.Styling.ContainsKey (style)) {
+                                       styling.Add (IFace.Styling [style]);
+                               }
+                       }
+                       if (IFace.Styling.ContainsKey (thisType.FullName)) {
+                               styling.Add (IFace.Styling [thisType.FullName]);
+                               if (string.IsNullOrEmpty (styleKey))
+                                       styleKey = thisType.FullName;
+                       }
+                       if (IFace.Styling.ContainsKey (thisType.Name)) {
+                               styling.Add (IFace.Styling [thisType.Name]);
+                               if (string.IsNullOrEmpty (styleKey))
+                                       styleKey = thisType.Name;
+                       }
+
+                       if (string.IsNullOrEmpty (styleKey))
+                               styleKey = thisType.FullName;
+
+                       //Reflexion being very slow compared to dyn method or delegates,
+                       //I compile the initial values coded in the CustomAttribs of the class,
+                       //all other instance of this type would not longer use reflexion to init properly
+                       //but will fetch the  dynamic initialisation method compiled for this precise type
+                       //TODO:measure speed gain.
+#region Delfault values Loading dynamic compilation
+                       DynamicMethod dm = null;
+                       ILGenerator il = null;
+
+                       dm = new DynamicMethod("dyn_loadDefValues", null, new Type[] { typeof (object) }, thisType, true);
+
+            il = dm.GetILGenerator(256);
+                       il.DeclareLocal(typeof (object));//store root
+                       il.Emit(OpCodes.Nop);
+                       //set local GraphicObject to root object passed as 1st argument
+                       il.Emit (OpCodes.Ldarg_0);
+                       il.Emit (OpCodes.Stloc_0);
+
+                       foreach (EventInfo ei in thisType.GetEvents(BindingFlags.Public | BindingFlags.Instance)) {
+                               string expression;
+                               if (!getDefaultEvent(ei, styling, out expression))
+                                       continue;
+                               //TODO:dynEventHandler could be cached somewhere, maybe a style instanciator class holding the styling delegate and bound to it.
+                               foreach (string exp in CompilerServices.splitOnSemiColumnOutsideAccolades(expression)) {
+                                       string trimed = exp.Trim();
+                                       if (trimed.StartsWith ("{", StringComparison.Ordinal)){
+                                               il.Emit (OpCodes.Ldloc_0);//load this as 1st arg of event Add
+
+                                               //push eventInfo as 1st arg of compile
+                                               il.Emit (OpCodes.Ldloc_0);
+                                               il.Emit (OpCodes.Call, CompilerServices.miGetType);
+                                               il.Emit (OpCodes.Ldstr, ei.Name);//push event name
+                                               il.Emit (OpCodes.Call, CompilerServices.miGetEvent);
+                                               //push expression as 2nd arg of compile
+                                               il.Emit (OpCodes.Ldstr, trimed.Substring (1, trimed.Length - 2));
+                                               //push null as 3rd arg, currentNode, not known when instanciing
+                                               il.Emit (OpCodes.Ldnull);
+                                               il.Emit (OpCodes.Call, CompilerServices.miCompileDynEventHandler);
+                                               il.Emit (OpCodes.Castclass, ei.EventHandlerType);
+                                               il.Emit (OpCodes.Callvirt, ei.AddMethod);
+                                       }else
+                                               Debug.WriteLine("error in styling, event not handled : " + trimed);
+                               }
+                       }
+
+                       foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
+                               if (pi.GetSetMethod () == null)
+                                       continue;
+                               XmlIgnoreAttribute xia = (XmlIgnoreAttribute)pi.GetCustomAttribute (typeof(XmlIgnoreAttribute));
+                               if (xia != null)
+                                       continue;
+
+                               object defaultValue;
+
+                               int styleIndex = -1;
+                               if (styling.Count > 0){
+                                       for (int i = 0; i < styling.Count; i++) {
+                                               if (styling[i].ContainsKey (pi.Name)){
+                                                       styleIndex = i;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (styleIndex >= 0){
+                                       if (pi.PropertyType.IsEnum)//maybe should be in parser..
+                                               defaultValue = Enum.Parse(pi.PropertyType, (string)styling[styleIndex] [pi.Name], true);
+                                       else
+                                               defaultValue = styling[styleIndex] [pi.Name];
+
+                                       #if DESIGN_MODE
+                                       if (defaultValue != null){
+                                               FileLocation fl = styling[styleIndex].Locations[pi.Name];
+                                               il.Emit (OpCodes.Ldloc_0);
+                                               il.Emit (OpCodes.Ldstr, pi.Name);
+                                               il.Emit (OpCodes.Ldstr, fl.FilePath);
+                                               il.Emit (OpCodes.Ldc_I4, fl.Line);
+                                               il.Emit (OpCodes.Ldc_I4, fl.Column);
+                                               il.Emit (OpCodes.Call, miDesignAddDefLoc);
+
+                                               il.Emit (OpCodes.Ldloc_0);
+                                               il.Emit (OpCodes.Ldfld, typeof(Widget).GetField("design_style_values"));
+                                               il.Emit (OpCodes.Ldstr, pi.Name);
+                                               il.Emit (OpCodes.Ldstr, defaultValue.ToString());
+                                               il.Emit (OpCodes.Call, CompilerServices.miDicStrStrAdd);
+                                       }
+                                       #endif
+
+                               }else {
+                                       DefaultValueAttribute dv = (DefaultValueAttribute)pi.GetCustomAttribute (typeof (DefaultValueAttribute));
+                                       if (dv == null)
+                                               continue;
+                                       defaultValue = dv.Value;
+                               }
+
+                               CompilerServices.EmitSetValue (il, pi, defaultValue);
+                       }
+                       il.Emit(OpCodes.Ret);
+                       #endregion
+
+                       try {
+                               IFace.DefaultValuesLoader[styleKey] = (Interface.LoaderInvoker)dm.CreateDelegate(typeof(Interface.LoaderInvoker));
+                               IFace.DefaultValuesLoader[styleKey] (this);
+                       } catch (Exception ex) {
+                               throw new Exception ("Error applying style <" + styleKey + ">:", ex);
+                       }
+
+                       #if DEBUG_LOG
+                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+                       #endif
+
+                       onInitialized (this, null);
+               }
+               protected virtual void onInitialized (object sender, EventArgs e){
+                       Initialized.Raise(sender, e);
+               }
+               bool getDefaultEvent(EventInfo ei, List<Style> styling,
+                       out string expression){
+                       expression = "";
+                       if (styling.Count > 0){
+                               for (int i = 0; i < styling.Count; i++) {
+                                       if (styling[i].ContainsKey (ei.Name)){
+                                               expression = (string)styling[i] [ei.Name];
+                                               return true;
+                                       }
+                               }
+                       }
+                       return false;
+               }
+#endregion
+
+               public virtual Widget FindByName(string nameToFind){
+                       return string.Equals(nameToFind, name, StringComparison.Ordinal) ? this : null;
+               }
+               public virtual bool Contains(Widget goToFind){
+                       return false;
+               }
+               /// <summary>
+               /// return true if this is contained inside go
+               /// </summary>
+               public bool IsOrIsInside(Widget go){
+                       if (this == go)
+                               return true;
+                       ILayoutable p = this.Parent;
+                       while (p != null) {
+                               if (p == go)
+                                       return true;
+                               p = p.Parent;
+                       }
+                       return false;
+               }
+
+               #region Drag&Drop
+               [DesignCategory ("DragAndDrop")][DefaultValue(false)]
+               public virtual bool AllowDrag {
+                       get { return allowDrag; }
+                       set {
+                               if (allowDrag == value)
+                                       return;
+                               allowDrag = value;
+                               NotifyValueChanged ("AllowDrag", allowDrag);
+                       }
+               }
+               [DesignCategory ("DragAndDrop")][DefaultValue(false)]
+               public virtual bool AllowDrop {
+                       get { return allowDrop; }
+                       set {
+                               if (allowDrop == value)
+                                       return;
+                               allowDrop = value;
+                               NotifyValueChanged ("AllowDrop", allowDrop);
+                       }
+               }
+
+//             public List<Type> AllowedDroppedTypes;
+//             public void AddAllowedDroppedType (Type newType){
+//                     if (AllowedDroppedTypes == null)
+//                             AllowedDroppedTypes = new List<Type> ();
+//                     AllowedDroppedTypes.Add (newType);
+//                     NotifyValueChanged ("AllowDrop", AllowDrop);
+//             }
+//             [XmlIgnore]public virtual bool AllowDrop {
+//                     get { return AllowedDroppedTypes?.Count>0; }
+//             }
+               [XmlIgnore]public virtual bool IsDragged {
+                       get { return isDragged; }
+                       set {
+                               if (isDragged == value)
+                                       return;
+                               isDragged = value;
+
+                               NotifyValueChanged ("IsDragged", IsDragged);
+                       }
+               }
+               /// <summary>
+               /// fired when drag and drop operation start
+               /// </summary>
+               protected virtual void onStartDrag (object sender, DragDropEventArgs e){
+                       IFace.HoverWidget = null;
+                       IsDragged = true;
+                       StartDrag.Raise (this, e);
+                       #if DEBUG_DRAGNDROP
+                       Debug.WriteLine(this.ToString() + " : START DRAG => " + e.ToString());
+                       #endif
+               }
+               /// <summary>
+               ///  Occured when dragging ends without dropping
+               /// </summary>
+               protected virtual void onEndDrag (object sender, DragDropEventArgs e){                  
+                       IsDragged = false;
+                       EndDrag.Raise (this, e);
+                       #if DEBUG_DRAGNDROP
+                       Debug.WriteLine(this.ToString() + " : END DRAG => " + e.ToString());
+                       #endif
+               }
+               protected virtual void onDragEnter (object sender, DragDropEventArgs e){
+                       e.DropTarget = this;
+                       DragEnter.Raise (this, e);
+                       #if DEBUG_DRAGNDROP
+                       Debug.WriteLine(this.ToString() + " : DRAG Enter => " + e.ToString());
+                       #endif
+               }
+               protected virtual void onDragLeave (object sender, DragDropEventArgs e){                        
+                       e.DropTarget = null;
+                       DragLeave.Raise (this, e);
+                       #if DEBUG_DRAGNDROP
+                       Debug.WriteLine(this.ToString() + " : DRAG Leave => " + e.ToString());
+                       #endif
+               }
+               protected virtual void onDrop (object sender, DragDropEventArgs e){                     
+                       IsDragged = false;
+                       Drop.Raise (this, e);
+                       //e.DropTarget.onDragLeave (this, e);//raise drag leave in target
+                       #if DEBUG_DRAGNDROP
+                       Debug.WriteLine(this.ToString() + " : DROP => " + e.ToString());
+                       #endif
+               }
+               public bool IsDropTarget {
+                       get { return IFace.DragAndDropOperation?.DropTarget == this; }
+               }
+
+               #endregion
+
+               #region Queuing
+               /// <summary>
+               /// Register old and new slot for clipping
+               /// </summary>
+               public virtual void ClippingRegistration(){
+                       #if DEBUG_LOG
+                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOClippingRegistration, this);
+                       #endif  
+                       parentRWLock.EnterReadLock ();
+                       if (parent != null) {                                   
+                               Parent.RegisterClip (LastPaintedSlot);
+                               Parent.RegisterClip (Slot);
+                       }
+                       parentRWLock.ExitReadLock ();
+                       #if DEBUG_LOG
+                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+                       #endif
+               }
+               /// <summary>
+               /// Add clip rectangle to this.clipping and propagate up to root
+               /// </summary>
+               /// <param name="clip">Clip rectangle</param>
+               public virtual void RegisterClip(Rectangle clip){
+                       #if DEBUG_LOG
+                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GORegisterClip, this);
+                       #endif
+                       Rectangle cb = ClientRectangle;
+                       Rectangle  r = clip + cb.Position;
+                       if (r.Right > cb.Right)
+                               r.Width -= r.Right - cb.Right;
+                       if (r.Bottom > cb.Bottom)
+                               r.Height -= r.Bottom - cb.Bottom;
+                       if (cacheEnabled && !IsDirty)
+                               Clipping.UnionRectangle (r);
+                       if (Parent == null)
+                               return;
+                       Widget p = Parent as Widget;
+                       if (p?.IsDirty == true && p?.CacheEnabled == true)
+                               return;
+                       Parent.RegisterClip (r + Slot.Position);
+                       #if DEBUG_LOG
+                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+                       #endif
+               }
+               /// <summary> Full update, content and layouting, taking care of sizing policy </summary>
+               [MethodImpl(MethodImplOptions.AggressiveInlining)]
+               public void RegisterForGraphicUpdate ()
+               {
+                       IsDirty = true;
+                       if (Width.IsFit || Height.IsFit)
+                               RegisterForLayouting (LayoutingType.Sizing);
+                       else if (RegisteredLayoutings == LayoutingType.None)
+                               IFace.EnqueueForRepaint (this);
+               }
+               /// <summary> query an update of the content without layouting changes</summary>
+               [MethodImpl(MethodImplOptions.AggressiveInlining)]
+               public void RegisterForRedraw ()
+               {
+                       IsDirty = true;
+                       if (RegisteredLayoutings == LayoutingType.None)
+                               IFace.EnqueueForRepaint (this);
+               }
+               #endregion
+
+               #region Layouting
+
+               /// <summary> return size of content + margins </summary>
+               protected virtual int measureRawSize (LayoutingType lt) {
+                       return lt == LayoutingType.Width ?
+                               contentSize.Width + 2 * margin: contentSize.Height + 2 * margin;
+               }
+               /// <summary> By default in groups, LayoutingType.ArrangeChildren is reset </summary>
+               public virtual void ChildrenLayoutingConstraints(ref LayoutingType layoutType){
+               }
+               public virtual bool ArrangeChildren { get { return false; } }
+               public virtual void RegisterForLayouting(LayoutingType layoutType){
+                       if (Parent == null)
+                               return;
+                       lock (IFace.LayoutMutex) {
+                               //prevent queueing same LayoutingType for this
+                               layoutType &= (~RegisteredLayoutings);
+
+                               if (layoutType == LayoutingType.None)
+                                       return;
+                               //dont set position for stretched item
+                               if (Width == Measure.Stretched)
+                                       layoutType &= (~LayoutingType.X);
+                               if (Height == Measure.Stretched)
+                                       layoutType &= (~LayoutingType.Y);
+
+                               if (!ArrangeChildren)
+                                       layoutType &= (~LayoutingType.ArrangeChildren);
+
+                               //apply constraints depending on parent type
+                               if (Parent is Widget)
+                                       (Parent as Widget).ChildrenLayoutingConstraints (ref layoutType);
+
+//                             //prevent queueing same LayoutingType for this
+                               layoutType &= (~RegisteredLayoutings);
+
+                               if (layoutType == LayoutingType.None)
+                                       return;
+
+                               //enqueue LQI LayoutingTypes separately
+                               if (layoutType.HasFlag (LayoutingType.Width))
+                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Width, this));
+                               if (layoutType.HasFlag (LayoutingType.Height))
+                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Height, this));
+                               if (layoutType.HasFlag (LayoutingType.X))
+                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.X, this));
+                               if (layoutType.HasFlag (LayoutingType.Y))
+                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Y, this));
+                               if (layoutType.HasFlag (LayoutingType.ArrangeChildren))
+                                       IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this));
+                       }
+               }
+
+               /// <summary> trigger dependant sizing component update </summary>
+               public virtual void OnLayoutChanges(LayoutingType  layoutType)
+               {
+                       switch (layoutType) {
+                       case LayoutingType.Width:
+                               RegisterForLayouting (LayoutingType.X);
+                               break;
+                       case LayoutingType.Height:
+                               RegisterForLayouting (LayoutingType.Y);
+                               break;
+                       }
+                       LayoutChanged.Raise (this, new LayoutingEventArgs (layoutType));
+               }
+               internal protected void raiseLayoutChanged(LayoutingEventArgs e){
+                       LayoutChanged.Raise (this, e);
+               }
+               /// <summary> Update layout component only one at a time, this is where the computation of alignement
+               /// and size take place.
+               /// The redrawing will only be triggered if final slot size has changed </summary>
+               /// <returns><c>true</c>, if layouting was possible, <c>false</c> if conditions were not
+               /// met and LQI has to be re-queued</returns>
+               public virtual bool UpdateLayout (LayoutingType layoutType)
+               {
+                       //unset bit, it would be reset if LQI is re-queued
+                       registeredLayoutings &= (~layoutType);
+
+                       switch (layoutType) {
+                       case LayoutingType.X:
+                               if (left == 0) {
+
+                                       if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width) ||
+                                           RegisteredLayoutings.HasFlag (LayoutingType.Width))
+                                               return false;
+
+                                       switch (horizontalAlignment) {
+                                       case HorizontalAlignment.Left:
+                                               Slot.X = 0;
+                                               break;
+                                       case HorizontalAlignment.Right:
+                                               Slot.X = Parent.ClientRectangle.Width - Slot.Width;
+                                               break;
+                                       case HorizontalAlignment.Center:
+                                               Slot.X = Parent.ClientRectangle.Width / 2 - Slot.Width / 2;
+                                               break;
+                                       }
+                               } else
+                                       Slot.X = left;
+
+                               if (LastSlots.X == Slot.X)
+                                       break;
+
+                               IsDirty = true;
+
+                               OnLayoutChanges (layoutType);
+
+                               LastSlots.X = Slot.X;
+                               break;
+                       case LayoutingType.Y:
+                               if (top == 0) {
+
+                                       if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height) ||
+                                           RegisteredLayoutings.HasFlag (LayoutingType.Height))
+                                               return false;
+
+                                       switch (verticalAlignment) {
+                                       case VerticalAlignment.Top://this could be processed even if parent Height is not known
+                                               Slot.Y = 0;
+                                               break;
+                                       case VerticalAlignment.Bottom:
+                                               Slot.Y = Parent.ClientRectangle.Height - Slot.Height;
+                                               break;
+                                       case VerticalAlignment.Center:
+                                               Slot.Y = Parent.ClientRectangle.Height / 2 - Slot.Height / 2;
+                                               break;
+                                       }
+                               } else
+                                       Slot.Y = top;
+
+                               if (LastSlots.Y == Slot.Y)
+                                       break;
+
+                               IsDirty = true;
+
+                               OnLayoutChanges (layoutType);
+
+                               LastSlots.Y = Slot.Y;
+                               break;
+                       case LayoutingType.Width:
+                               if (isVisible) {
+                                       if (Width.IsFixed)
+                                               Slot.Width = Width;
+                                       else if (Width == Measure.Fit) {
+                                               Slot.Width = measureRawSize (LayoutingType.Width);
+                                       } else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width))
+                                               return false;
+                                       else if (Width == Measure.Stretched)
+                                               Slot.Width = Parent.ClientRectangle.Width;
+                                       else
+                                               Slot.Width = (int)Math.Round ((double)(Parent.ClientRectangle.Width * Width) / 100.0);
+
+                                       if (Slot.Width < 0)
+                                               return false;
+
+                                       //size constrain
+                                       if (Slot.Width < minimumSize.Width) {
+                                               Slot.Width = minimumSize.Width;
+                                               //NotifyValueChanged ("WidthPolicy", Measure.Stretched);
+                                       } else if (Slot.Width > maximumSize.Width && maximumSize.Width > 0) {
+                                               Slot.Width = maximumSize.Width;
+                                               //NotifyValueChanged ("WidthPolicy", Measure.Stretched);
+                                       }
+                               } else
+                                       Slot.Width = 0;
+
+                               if (LastSlots.Width == Slot.Width)
+                                       break;
+
+                               IsDirty = true;
+
+                               OnLayoutChanges (layoutType);
+
+                               LastSlots.Width = Slot.Width;
+                               break;
+                       case LayoutingType.Height:
+                               if (isVisible) {
+                                       if (Height.IsFixed)
+                                               Slot.Height = Height;
+                                       else if (Height == Measure.Fit) {
+                                               Slot.Height = measureRawSize (LayoutingType.Height);
+                                       } else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height))
+                                               return false;
+                                       else if (Height == Measure.Stretched)
+                                               Slot.Height = Parent.ClientRectangle.Height;
+                                       else
+                                               Slot.Height = (int)Math.Round ((double)(Parent.ClientRectangle.Height * Height) / 100.0);
+
+                                       if (Slot.Height < 0)
+                                               return false;
+
+                                       //size constrain
+                                       if (Slot.Height < minimumSize.Height) {
+                                               Slot.Height = minimumSize.Height;
+                                               //NotifyValueChanged ("HeightPolicy", Measure.Stretched);
+                                       } else if (Slot.Height > maximumSize.Height && maximumSize.Height > 0) {
+                                               Slot.Height = maximumSize.Height;
+                                               //NotifyValueChanged ("HeightPolicy", Measure.Stretched);
+                                       }
+                               } else
+                                       Slot.Height = 0;
+
+                               if (LastSlots.Height == Slot.Height)
+                                       break;
+
+                               IsDirty = true;
+
+                               OnLayoutChanges (layoutType);
+
+                               LastSlots.Height = Slot.Height;
+                               break;
+                       }
+
+                       //if no layouting remains in queue for item, registre for redraw
+                       if (this.registeredLayoutings == LayoutingType.None && IsDirty)
+                               IFace.EnqueueForRepaint (this);
+
+                       return true;
+               }
+               #endregion
+
+               #region Rendering
+               /// <summary> This is the common overridable drawing routine to create new widget </summary>
+               protected virtual void onDraw(Context gr)
+               {
+                       #if DEBUG_LOG
+                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GODraw, this);
+                       #endif
+
+                       Rectangle rBack = new Rectangle (Slot.Size);
+
+                       background.SetAsSource (gr, rBack);
+                       CairoHelpers.CairoRectangle (gr, rBack, cornerRadius);
+                       gr.Fill ();
+
+                       #if DEBUG_LOG
+                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+                       #endif
+               }
+
+               /// <summary>
+               /// Internal drawing context creation on a cached surface limited to slot size
+               /// this trigger the effective drawing routine </summary>
+               protected virtual void RecreateCache ()
+               {
+                       #if DEBUG_LOG
+                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GORecreateCache, this);
+                       #endif
+
+                       /*if (bmp == null)
+                               bmp = IFace.surf.CreateSimilar (Content.ColorAlpha, Slot.Width, Slot.Height);
+                       else if (LastPaintedSlot.Width != Slot.Width || LastPaintedSlot.Height != Slot.Height)
+                               bmp.SetSize (Slot.Width, Slot.Height);*/
+                       bmp?.Dispose ();
+                       //bmp = IFace.surf.CreateSimilar (Content.ColorAlpha, Slot.Width, Slot.Height);
+                       bmp = new ImageSurface(Format.Argb32, Slot.Width, Slot.Height);
+
+                       using (Context gr = new Context (bmp)) {
+                               gr.Antialias = Interface.Antialias;
+                               onDraw (gr);
+                       }
+
+                       IsDirty = false;
+
+                       #if DEBUG_LOG
+                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+                       #endif
+               }
+               protected virtual void UpdateCache(Context ctx){
+                       #if DEBUG_LOG
+                       DbgEvent dbgEvt = DebugLog.AddEvent(DbgEvtType.GOUpdateCacheAndPaintOnCTX, this);
+                       #endif
+
+                       Rectangle rb = Slot + Parent.ClientRectangle.Position;
+                       if (clearBackground) {
+                                       ctx.Save ();
+                                       ctx.Operator = Operator.Clear;
+                                       ctx.Rectangle (rb);
+                                       ctx.Fill ();
+                                       ctx.Restore ();
+                       }
+
+                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
+                       ctx.Paint ();
+                       Clipping.Dispose ();
+                       Clipping = new Region ();
+                       #if DEBUG_LOG
+                       dbgEvt.end = DebugLog.chrono.ElapsedTicks;
+                       #endif
+               }
+               /// <summary> Chained painting routine on the parent context of the actual cached version
+               /// of the widget </summary>
+               public virtual void Paint (ref Context ctx)
+               {
+                       #if DEBUG_LOG
+                       DebugLog.AddEvent(DbgEvtType.GOPaint, this);
+                       #endif
+                       //TODO:this test should not be necessary
+                       if (Slot.Height < 0 || Slot.Width < 0 || parent == null)
+                               return;
+                       lock (this) {
+                               if (cacheEnabled) {
+                                       if (Slot.Width > Interface.MaxCacheSize || Slot.Height > Interface.MaxCacheSize)
+                                               cacheEnabled = false;
+                               }
+
+                               if (cacheEnabled) {
+                                       if (IsDirty)
+                                               RecreateCache ();
+
+                                       UpdateCache (ctx);
+                                       if (!isEnabled)                                         
+                                               paintDisabled (ctx, Slot + Parent.ClientRectangle.Position);                                    
+                               } else {
+                                       Rectangle rb = Slot + Parent.ClientRectangle.Position;
+                                       ctx.Save ();
+
+                                       ctx.Translate (rb.X, rb.Y);
+
+                                       onDraw (ctx);
+                                       if (!isEnabled)
+                                               paintDisabled (ctx, Slot);
+
+                                       ctx.Restore ();
+                               }
+                               LastPaintedSlot = Slot;
+                       }
+               }
+               void paintDisabled(Context gr, Rectangle rb){
+                       gr.Operator = Operator.Xor;
+                       gr.SetSourceRGBA (0.6, 0.6, 0.6, 0.3);
+                       gr.Rectangle (rb);
+                       gr.Fill ();
+                       gr.Operator = Operator.Over;
+               }
+               #endregion
+
+        #region Keyboard handling
+               public virtual void onKeyDown(object sender, KeyEventArgs e){
+                       if (KeyDown != null)
+                               KeyDown.Invoke (this, e);
+                       else if (!e.Handled)
+                               FocusParent?.onKeyDown (sender, e);
+               }
+               public virtual void onKeyUp(object sender, KeyEventArgs e){
+                       if (KeyUp != null)
+                               KeyUp.Invoke (this, e);
+                       else if (!e.Handled)
+                               FocusParent?.onKeyUp (sender, e);
+               }
+               public virtual void onKeyPress(object sender, KeyPressEventArgs e){
+                       if (KeyPress != null)
+                               KeyPress.Invoke (this, e);
+                       else if (!e.Handled)
+                               FocusParent?.onKeyPress (sender, e);
+               }
+        #endregion
+
+               #region Mouse handling
+               /// <summary>
+               /// Recursive local coordinate point test.
+               /// After test on parent, point m is in local coord system.
+               /// </summary>
+               /// <returns>return true, if point is in the bounds of this control</returns>
+               /// <param name="m">by ref point to test, init value is not kept</param>
+               public virtual bool PointIsIn(ref Point m)
+               {
+                       if (parent == null)
+                               return false;
+                       if (!(isVisible & isEnabled)||IsDragged)
+                               return false;
+                       if (!parent.PointIsIn(ref m))
+                               return false;
+                       m -= (parent.getSlot().Position + parent.ClientRectangle.Position) ;
+                       return Slot.ContainsOrIsEqual (m);                                      
+               }
+               public virtual bool MouseIsIn(Point m)
+               {                       
+                       return (!(isVisible & isEnabled)||IsDragged) ? false : PointIsIn (ref m);
+               }
+               public virtual void checkHoverWidget(MouseMoveEventArgs e)
+               {
+                       if (IFace.HoverWidget != this) {
+                               IFace.HoverWidget = this;
+                               onMouseEnter (this, e);
+                       }
+
+                       //this.onMouseMove (this, e);//without this, window border doesn't work, should be removed
+               }
+               public virtual void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       if (allowDrag & hasFocus & e.Mouse.LeftButton == ButtonState.Pressed) {
+                               if (IFace.DragAndDropOperation == null) {
+                                       IFace.DragAndDropOperation = new DragDropEventArgs (this);
+                                       onStartDrag (this, IFace.DragAndDropOperation);
+                               }
+                       }
+
+                       //dont bubble event if dragged, mouse move is routed directely from iface
+                       //to let other control behind have mouse entering
+                       if (isDragged)
+                               return;
+
+                       if (MouseMove != null)
+                               MouseMove.Invoke (this, e);                     
+                       else if (!e.Handled)
+                               FocusParent?.onMouseMove (sender, e);
+
+
+               }
+               public virtual void onMouseDown(object sender, MouseButtonEventArgs e){
+#if DEBUG_FOCUS
+                       Debug.WriteLine("MOUSE DOWN => " + this.ToString());
+#endif
+
+                       if (e.Button == MouseButton.Right && contextCommands != null) {
+                               IFace.ShowContextMenu (this);
+                               e.Handled = true;
+                       }
+
+                       if (MouseDown != null)
+                               MouseDown?.Invoke (this, e);
+                       else if (!e.Handled)
+                               FocusParent?.onMouseDown (sender, e);
+               }
+               public virtual void onMouseUp(object sender, MouseButtonEventArgs e){
+#if DEBUG_FOCUS
+                       Debug.WriteLine("MOUSE UP => " + this.ToString());
+#endif
+
+                       if (IFace.DragAndDropOperation != null){
+                               if (IFace.DragAndDropOperation.DragSource == this) {
+                                       if (IFace.DragAndDropOperation.DropTarget != null)
+                                               onDrop (this, IFace.DragAndDropOperation);
+                                       else
+                                               onEndDrag (this, IFace.DragAndDropOperation);
+                                       IFace.DragAndDropOperation = null;
+                               }
+                       }
+                       if (MouseUp != null)
+                               MouseUp.Invoke (this, e);
+                       else if (!e.Handled)
+                               FocusParent?.onMouseUp (sender, e);
+               }
+               public virtual void onMouseClick(object sender, MouseButtonEventArgs e){
+#if DEBUG_FOCUS
+                       Debug.WriteLine("CLICK => " + this.ToString());
+#endif
+                       if (MouseClick != null)
+                               MouseClick.Invoke (this, e);
+                       else if (!e.Handled)
+                               FocusParent?.onMouseClick (sender, e);
+               }
+               public virtual void onMouseDoubleClick(object sender, MouseButtonEventArgs e){
+#if DEBUG_FOCUS
+                       Debug.WriteLine("DOUBLE CLICK => " + this.ToString());
+#endif
+                       if (MouseDoubleClick != null)                   
+                               MouseDoubleClick.Invoke (this, e);
+                       else if (!e.Handled)
+                               FocusParent?.onMouseDoubleClick (sender, e);
+               }
+               public virtual void onMouseWheel(object sender, MouseWheelEventArgs e){
+                       if (MouseWheelChanged != null)
+                               MouseWheelChanged.Invoke (this, e);
+                       else if (!e.Handled)
+                               FocusParent?.onMouseWheel (sender, e);
+               }
+               public virtual void onMouseEnter(object sender, MouseMoveEventArgs e)
+               {
+                       #if DEBUG_FOCUS
+                       Debug.WriteLine("MouseEnter => " + this.ToString());
+#endif
+
+                       IFace.MouseCursor = mouseCursor;
+
+                       if (IFace.DragAndDropOperation != null) {
+                               Widget g = this;
+                               while (g != null) {
+                                       if (g.AllowDrop) {
+                                               if (IFace.DragAndDropOperation.DragSource != this && IFace.DragAndDropOperation.DropTarget != this) {
+                                                       if (IFace.DragAndDropOperation.DropTarget != null)
+                                                               IFace.DragAndDropOperation.DropTarget.onDragLeave (this, IFace.DragAndDropOperation);
+                                                       g.onDragEnter (this, IFace.DragAndDropOperation);
+                                               }
+                                               break;
+                                       }
+                                       g = g.FocusParent;
+                               }
+                       }
+
+                       MouseEnter.Raise (this, e);
+               }
+               public virtual void onMouseLeave(object sender, MouseMoveEventArgs e)
+               {
+                       #if DEBUG_FOCUS
+                       Debug.WriteLine("MouseLeave => " + this.ToString());
+                       #endif
+
+                       MouseLeave.Raise (this, e);
+               }
+
+               #endregion
+
+               protected virtual void onFocused(object sender, EventArgs e){
+                       #if DEBUG_FOCUS
+                       Debug.WriteLine("Focused => " + this.ToString());
+                       #endif
+                       Focused.Raise (this, e);
+               }
+               protected virtual void onUnfocused(object sender, EventArgs e){
+                       #if DEBUG_FOCUS
+                       Debug.WriteLine("UnFocused => " + this.ToString());
+                       #endif
+                       Unfocused.Raise (this, e);
+               }
+
+               public virtual void onEnable(object sender, EventArgs e){
+                       Enabled.Raise (this, e);
+               }
+               public virtual void onDisable(object sender, EventArgs e){
+                       Disabled.Raise (this, e);
+               }
+               protected virtual void onParentChanged(object sender, DataSourceChangeEventArgs e) {
+                       ParentChanged.Raise (this, e);
+                       if (logicalParent == null)
+                               LogicalParentChanged.Raise (this, e);
+               }
+               protected virtual void onLogicalParentChanged(object sender, DataSourceChangeEventArgs e) {
+                       LogicalParentChanged.Raise (this, e);
+               }
+               internal void ClearTemplateBinding(){
+                       #if DEBUG_UPDATE
+                       Debug.WriteLine (string.Format("ClearTemplateBinding: {0}", this.ToString()));
+                       #endif
+                       if (ValueChanged == null)
+                               return;
+                       EventInfo eiEvt = this.GetType().GetEvent ("ValueChanged");
+                       foreach (Delegate d in ValueChanged.GetInvocationList()) {
+                               if (d.Method.Name == "dyn_tmpValueChanged") {
+                                       eiEvt.RemoveEventHandler (this, d);
+                                       #if DEBUG_BINDING
+                                       Debug.WriteLine ("\t{0} template binding handler removed in {1} for: {2}", d.Method.Name, this, "ValueChanged");
+                                       #endif
+                               }
+                       }
+               }
+               public override string ToString ()
+               {
+                       string tmp ="";
+
+                       if (Parent != null)
+                               tmp = Parent.ToString () + tmp;
+                       #if DEBUG_LAYOUTING
+                       return Name == "unamed" ? tmp + "." + this.GetType ().Name + GraphicObjects.IndexOf(this).ToString(): tmp + "." + Name;
+                       #else
+                       return string.IsNullOrEmpty(Name) ? tmp + "." + this.GetType ().Name : tmp + "." + Name;
+                       #endif
+               }
+               /// <summary>
+               /// Checks to handle when widget is removed from the visible graphic tree
+               /// </summary>
+               void unshownPostActions () {
+                       if (IFace.HoverWidget != null) {
+                               if (IFace.HoverWidget.IsOrIsInside (this)) {
+                                       IFace.HoverWidget = null;
+                                       IFace.OnMouseMove (IFace.Mouse.X, IFace.Mouse.Y);
+                               }
+                       }
+                       if (IFace.ActiveWidget != null) {
+                               if (IFace.ActiveWidget.IsOrIsInside (this))
+                                       IFace.ActiveWidget = null;
+                       }
+                       if (IFace.FocusedWidget != null) {
+                               if (IFace.FocusedWidget.IsOrIsInside (this))
+                                       IFace.FocusedWidget = null;
+                       }                                       
+               }
+       }
+}
diff --git a/Crow/src/Widgets/Window.cs b/Crow/src/Widgets/Window.cs
new file mode 100644 (file)
index 0000000..22ad640
--- /dev/null
@@ -0,0 +1,466 @@
+//
+// Window.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.Xml.Serialization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace Crow
+{
+       public class Window : TemplatedContainer
+       {
+               public enum Direction
+               {
+                       None,
+                       N,
+                       S,
+                       E,
+                       W,
+                       NW,
+                       NE,
+                       SW,
+                       SE,
+               }
+
+               string _icon;
+               bool resizable;
+               bool movable;
+               bool modal;
+               protected bool hoverBorder = false;
+               bool alwaysOnTop = false;
+               Fill titleBarBackground = Color.SteelBlue;
+               Fill titleBarForeground = Color.White;
+
+               Rectangle savedBounds;
+               bool _minimized = false;
+
+               Direction currentDirection = Direction.None;
+
+               #region Events
+               public event EventHandler Closing;
+               public event EventHandler Maximized;
+               public event EventHandler Unmaximized;
+               public event EventHandler Minimize;
+               #endregion
+
+               #region CTOR
+               protected Window() : base(){}
+               public Window (Interface iface) : base(iface){}
+               #endregion
+
+               #region TemplatedContainer overrides
+               protected override void loadTemplate(Widget template = null)
+               {
+                       base.loadTemplate (template);
+
+                       NotifyValueChanged ("ShowNormal", false);
+                       NotifyValueChanged ("ShowMinimize", true);
+                       NotifyValueChanged ("ShowMaximize", true);
+               }
+               #endregion
+
+               #region public properties
+               [DefaultValue("#Crow.Icons.crow.svg")]
+               public string Icon {
+                       get { return _icon; } 
+                       set {
+                               if (_icon == value)
+                                       return;
+                               _icon = value;
+                               NotifyValueChanged ("Icon", _icon);
+                       }
+               } 
+               /// <summary>
+               /// Background of the title bar if any.
+               /// </summary>
+               [DefaultValue("vgradient|0:Onyx|1:SteelBlue")]
+               public virtual Fill TitleBarBackground {
+                       get { return titleBarBackground; }
+                       set {
+                               if (titleBarBackground == value)
+                                       return;
+                               titleBarBackground = value;
+                               NotifyValueChanged ("TitleBarBackground", titleBarBackground);
+                               RegisterForRedraw ();
+                       }
+               }
+               /// <summary>
+               /// Foreground of the title bar, usualy used for the window caption color.
+               /// </summary>
+               [DefaultValue("White")]
+               public virtual Fill TitleBarForeground {
+                       get { return titleBarForeground; }
+                       set {
+                               if (titleBarForeground == value)
+                                       return;
+                               titleBarForeground = value;
+                               NotifyValueChanged ("TitleBarForeground", titleBarForeground);
+                               RegisterForRedraw ();
+                       }
+               }
+               [DefaultValue(true)]
+               public bool Resizable {
+                       get {
+                               return resizable;
+                       }
+                       set {
+                               if (resizable == value)
+                                       return;
+                               resizable = value;
+                               NotifyValueChanged ("Resizable", resizable);
+                       }
+               }
+               [DefaultValue(true)]
+               public bool Movable {
+                       get {
+                               return movable;
+                       }
+                       set {
+                               if (movable == value)
+                                       return;
+                               movable = value;
+                               NotifyValueChanged ("Movable", movable);
+                       }
+               }
+               [DefaultValue(false)]
+               public bool Modal {
+                       get {
+                               return modal;
+                       }
+                       set {
+                               if (modal == value)
+                                       return;
+                               modal = value;
+                               NotifyValueChanged ("Modal", modal);
+                       }
+               }
+               [DefaultValue(false)]
+               public bool IsMinimized {
+                       get { return _minimized; }
+                       set{
+                               if (value == IsMinimized)
+                                       return;
+
+                               _minimized = value;
+                               _contentContainer.Visible = !_minimized;
+
+                               NotifyValueChanged ("IsMinimized", _minimized);
+                       }
+               }
+               [XmlIgnore]public bool IsMaximized {
+                       get { return Width == Measure.Stretched & Height == Measure.Stretched & !_minimized; }
+               }
+               [XmlIgnore]public bool IsNormal {
+                       get { return !(IsMaximized|_minimized); }
+               }
+               [DefaultValue(false)]
+               public bool AlwaysOnTop {
+                       get {
+                               return modal ? true : alwaysOnTop;
+                       }
+                       set {
+                               if (alwaysOnTop == value)
+                                       return;
+                               
+                               alwaysOnTop = value;
+
+                               if (AlwaysOnTop && Parent != null)
+                                       IFace.PutOnTop (this);
+
+                               NotifyValueChanged ("AlwaysOnTop", AlwaysOnTop);
+                       }
+               }
+//             [DefaultValue(WindowState.Normal)]
+//             public virtual WindowState State {
+//                     get { return _state; }
+//                     set {
+//                             if (_state == value)
+//                                     return;
+//                             _state = value;
+//                             NotifyValueChanged ("State", _state);
+//                             NotifyValueChanged ("IsNormal", IsNormal);
+//                             NotifyValueChanged ("IsMaximized", IsMaximized);
+//                             NotifyValueChanged ("IsMinimized", IsMinimized);
+//                             NotifyValueChanged ("IsNotMinimized", IsNotMinimized);
+//                     }
+//             } 
+               #endregion
+
+               /// <summary>
+               /// Moves the and resize with the same function entry point, the direction give the kind of move or resize
+               /// </summary>
+               /// <param name="XDelta">mouse delta on the X axis</param>
+               /// <param name="YDelta">mouse delta on the Y axis</param>
+               /// <param name="currentDirection">Current Direction of the operation, none for moving, other value for resizing in the given direction</param>
+               public void MoveAndResize (int XDelta, int YDelta, Direction currentDirection = (Direction)0) {
+                       int currentLeft = this.Left;
+                       int currentTop = this.Top;
+                       int currentWidth, currentHeight;
+
+                       if (currentLeft == 0) {
+                               currentLeft = this.Slot.Left;
+                               this.Left = currentLeft;
+                       }
+                       if (currentTop == 0) {
+                               currentTop = this.Slot.Top;
+                               this.Top = currentTop;
+                       }
+                       if (this.Width.IsFixed)
+                               currentWidth = this.Width;
+                       else
+                               currentWidth = this.Slot.Width;
+
+                       if (this.Height.IsFixed)
+                               currentHeight = this.Height;
+                       else
+                               currentHeight = this.Slot.Height;
+
+                       switch (currentDirection) {
+                       case Direction.None:
+                               this.Left = currentLeft + XDelta;                               
+                               this.Top = currentTop + YDelta;
+                               break;
+                       case Direction.N:
+                               this.Height = currentHeight - YDelta;
+                               if (this.Height == currentHeight - YDelta)
+                                       this.Top = currentTop + YDelta;
+                               break;
+                       case Direction.S:
+                               this.Height = currentHeight + YDelta;
+                               break;
+                       case Direction.W:
+                               this.Width = currentWidth - XDelta;
+                               if (this.Width == currentWidth - XDelta)
+                                       this.Left = currentLeft + XDelta;
+                               break;
+                       case Direction.E:
+                               this.Width = currentWidth + XDelta;
+                               break;
+                       case Direction.NW:
+                               this.Height = currentHeight - YDelta;
+                               if (this.Height == currentHeight - YDelta)
+                                       this.Top = currentTop + YDelta;
+                               this.Width = currentWidth - XDelta;
+                               if (this.Width == currentWidth - XDelta)
+                                       this.Left = currentLeft + XDelta;
+                               break;
+                       case Direction.NE:
+                               this.Height = currentHeight - YDelta;
+                               if (this.Height == currentHeight - YDelta)
+                                       this.Top = currentTop + YDelta;
+                               this.Width = currentWidth + XDelta;
+                               break;
+                       case Direction.SW:
+                               this.Width = currentWidth - XDelta;
+                               if (this.Width == currentWidth - XDelta)
+                                       this.Left = currentLeft + XDelta;
+                               this.Height = currentHeight + YDelta;
+                               break;
+                       case Direction.SE:
+                               this.Height = currentHeight + YDelta;
+                               this.Width = currentWidth + XDelta;
+                               break;
+                       }                       
+               }
+
+               #region GraphicObject Overrides
+               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               {
+                       base.onMouseMove (sender, e);
+
+                       Interface otkgw = IFace;
+
+                       /*if (!hoverBorder) {
+                               currentDirection = Direction.None;
+                               IFace.MouseCursor = MouseCursor.Arrow;
+                               return;
+                       }*/
+
+                       if (this.HasFocus && movable) {
+                               if (e.Mouse.IsButtonDown (MouseButton.Left)) {
+                                       MoveAndResize (e.XDelta, e.YDelta, currentDirection);
+                                       return;
+                               }
+                       }
+                       if (Resizable) {
+                               Direction lastDir = currentDirection;
+
+                               if (Math.Abs (e.Position.Y - this.Slot.Y) < Interface.BorderThreshold) {
+                                       if (Math.Abs (e.Position.X - this.Slot.X) < Interface.BorderThreshold)
+                                               currentDirection = Direction.NW;
+                                       else if (Math.Abs (e.Position.X - this.Slot.Right) < Interface.BorderThreshold)
+                                               currentDirection = Direction.NE;
+                                       else
+                                               currentDirection = Direction.N;
+                               } else if (Math.Abs (e.Position.Y - this.Slot.Bottom) < Interface.BorderThreshold) {
+                                       if (Math.Abs (e.Position.X - this.Slot.X) < Interface.BorderThreshold)
+                                               currentDirection = Direction.SW;
+                                       else if (Math.Abs (e.Position.X - this.Slot.Right) < Interface.BorderThreshold)
+                                               currentDirection = Direction.SE;
+                                       else
+                                               currentDirection = Direction.S;
+                               } else if (Math.Abs (e.Position.X - this.Slot.X) < Interface.BorderThreshold)
+                                       currentDirection = Direction.W;
+                               else if (Math.Abs (e.Position.X - this.Slot.Right) < Interface.BorderThreshold)
+                                       currentDirection = Direction.E;
+                               else
+                                       currentDirection = Direction.None;
+
+                               if (currentDirection != lastDir) {
+                                       switch (currentDirection) {
+                                       case Direction.None:
+                                               otkgw.MouseCursor = MouseCursor.Move;
+                                               break;
+                                       case Direction.N:
+                                               otkgw.MouseCursor = MouseCursor.Top;
+                                               break;
+                                       case Direction.S:
+                                               otkgw.MouseCursor = MouseCursor.Bottom;
+                                               break;
+                                       case Direction.E:
+                                               otkgw.MouseCursor = MouseCursor.Right;
+                                               break;
+                                       case Direction.W:
+                                               otkgw.MouseCursor = MouseCursor.Left;
+                                               break;
+                                       case Direction.NW:
+                                               otkgw.MouseCursor = MouseCursor.TopLeft;
+                                               break;
+                                       case Direction.NE:
+                                               otkgw.MouseCursor = MouseCursor.TopRight;
+                                               break;
+                                       case Direction.SW:
+                                               otkgw.MouseCursor = MouseCursor.BottomLeft;
+                                               break;
+                                       case Direction.SE:
+                                               otkgw.MouseCursor = MouseCursor.BottomRight;
+                                               break;
+                                       }
+                               }                               
+                       }                               
+               }
+               public override void onMouseDown (object sender, MouseButtonEventArgs e)
+               {
+                       base.onMouseDown (sender, e);
+               }
+               public override bool MouseIsIn (Point m)
+               {
+                       return modal ? true : base.MouseIsIn (m);
+               }
+               #endregion
+
+               protected void onMaximized (object sender, EventArgs e){
+                       lock (IFace.LayoutMutex) {
+                               if (!IsMinimized)
+                                       savedBounds = this.LastPaintedSlot;
+                               this.Left = this.Top = 0;
+                               this.RegisterForLayouting (LayoutingType.Positioning);
+                               this.Width = this.Height = Measure.Stretched;
+                               IsMinimized = false;
+                               Resizable = false;
+                               NotifyValueChanged ("ShowNormal", true);
+                               NotifyValueChanged ("ShowMinimize", true);
+                               NotifyValueChanged ("ShowMaximize", false);
+                       }
+
+                       Maximized.Raise (sender, e);
+               }
+               protected void onUnmaximized (object sender, EventArgs e){
+                       lock (IFace.LayoutMutex) {
+                               this.Left = savedBounds.Left;
+                               this.Top = savedBounds.Top;
+                               this.Width = savedBounds.Width;
+                               this.Height = savedBounds.Height;
+                               IsMinimized = false;
+                               Resizable = true;
+                               NotifyValueChanged ("ShowNormal", false);
+                               NotifyValueChanged ("ShowMinimize", true);
+                               NotifyValueChanged ("ShowMaximize", true);
+                       }
+
+                       Unmaximized.Raise (sender, e);
+               }
+               protected void onMinimized (object sender, EventArgs e){
+                       lock (IFace.LayoutMutex) {
+                               if (IsNormal)
+                                       savedBounds = this.LastPaintedSlot;
+                               Width = 200;
+                               Height = 20;
+                               Resizable = false;
+                               IsMinimized = true;
+                               NotifyValueChanged ("ShowNormal", true);
+                               NotifyValueChanged ("ShowMinimize", false);
+                               NotifyValueChanged ("ShowMaximize", true);
+                       }
+
+                       Minimize.Raise (sender, e);
+               }
+               protected virtual void onBorderMouseLeave (object sender, MouseMoveEventArgs e)
+               {
+                       hoverBorder = false;
+                       currentDirection = Direction.None;
+                       IFace.MouseCursor = MouseCursor.Arrow;
+               }
+               protected virtual void onBorderMouseEnter (object sender, MouseMoveEventArgs e)
+               {
+                       hoverBorder = true;
+               }
+
+
+               protected void butQuitPress (object sender, MouseButtonEventArgs e)
+               {
+                       IFace.MouseCursor = MouseCursor.Arrow;
+                       close ();
+               }
+
+               protected virtual void close(){
+                       Closing.Raise (this, null);
+                       if (Parent is Interface)
+                               (Parent as Interface).DeleteWidget (this);
+                       else {
+                               Widget p = Parent as Widget;
+                               if (p is Group) {
+                                       lock (IFace.UpdateMutex) {
+                                               RegisterClip (p.ScreenCoordinates (p.LastPaintedSlot));
+                                               (p as Group).DeleteChild (this);
+                                       }
+                                       //(Parent as Group).RegisterForRedraw ();
+                               } else if (Parent is PrivateContainer)
+                                       (Parent as Container).Child = null;
+                       }
+               }
+
+               public static Window Show (Interface iface, string imlPath, bool modal = false){
+                       lock (iface.UpdateMutex) {
+                               Window w = iface.Load (imlPath) as Window;
+                               w.Modal = modal;
+                               return w;
+                       }
+               }
+       }
+}
+
diff --git a/Crow/src/Widgets/Wrapper.cs b/Crow/src/Widgets/Wrapper.cs
new file mode 100644 (file)
index 0000000..cc31985
--- /dev/null
@@ -0,0 +1,251 @@
+//
+// Wrapper.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;
+
+namespace Crow
+{
+       /// <summary>
+       /// group control that arrange its children in a direction and jump to
+       /// the next line or row when no room is left
+       /// </summary>
+       public class Wrapper : GenericStack
+       {
+               #region CTOR
+               protected Wrapper() : base(){}
+               public Wrapper (Interface iface) : base(iface){}
+               #endregion
+
+               #region Group Overrides
+               public override void ChildrenLayoutingConstraints (ref LayoutingType layoutType)
+               {
+                       layoutType &= (~LayoutingType.Positioning);
+               }
+               public override void ComputeChildrenPositions()
+               {
+                       int dx = 0;
+                       int dy = 0;
+
+                       if (Orientation == Orientation.Vertical) {
+                               int tallestChild = 0;
+                               foreach (Widget c in Children) {
+                                       if (!c.Visible)
+                                               continue;
+                                       if (dx + c.Slot.Width > ClientRectangle.Width) {
+                                               dx = 0;
+                                               dy += tallestChild + Spacing;
+                                               c.Slot.X = dx;
+                                               c.Slot.Y = dy;
+                                               tallestChild = c.Slot.Height;
+                                       } else {
+                                               if (tallestChild < c.Slot.Height)
+                                                       tallestChild = c.Slot.Height;
+                                               c.Slot.X = dx;
+                                               c.Slot.Y = dy;
+                                       }
+                                       dx += c.Slot.Width + Spacing;
+                               }
+                       } else {
+                               int largestChild = 0;
+                               foreach (Widget c in Children) {
+                                       if (!c.Visible)
+                                               continue;
+                                       if (dy + c.Slot.Height > ClientRectangle.Height) {
+                                               dy = 0;
+                                               dx += largestChild + Spacing;
+                                               c.Slot.X = dx;
+                                               c.Slot.Y = dy;
+                                               largestChild = c.Slot.Width;
+                                       } else {
+                                               if (largestChild < c.Slot.Width)
+                                                       largestChild = c.Slot.Width;
+                                               c.Slot.X = dx;
+                                               c.Slot.Y = dy;
+                                       }
+                                       dy += c.Slot.Height + Spacing;
+                               }
+                       }
+                       IsDirty = true;
+               }
+               public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
+               {
+                       //children can't stretch in a wrapper
+                       Widget go = sender as Widget;
+                       //System.Diagnostics.Debug.WriteLine ("wrapper child layout change: " + go.LastSlots.ToString() + " => " + go.Slot.ToString());
+                       switch (arg.LayoutType) {
+                       case LayoutingType.Width:
+                               if (Orientation == Orientation.Horizontal && go.Width.Units == Unit.Percent){
+                                       go.Width = Measure.Fit;
+                                       return;
+                               }
+                               this.RegisterForLayouting (LayoutingType.Width);
+                               break;
+                       case LayoutingType.Height:
+                               if (Orientation == Orientation.Vertical && go.Height.IsRelativeToParent) {
+                                       go.Height = Measure.Fit;
+                                       return;
+                               }
+                               this.RegisterForLayouting (LayoutingType.Height);
+                               break;
+                       default:
+                               return;
+                       }
+                       this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+               }
+               #endregion
+
+               #region GraphicObject Overrides
+               protected override int measureRawSize (LayoutingType lt)
+               {
+                       int tmp = 0;
+                       //Wrapper can't fit in the opposite direction of the wrapper, this func is called only if Fit
+                       if (lt == LayoutingType.Width) {
+                               if (Orientation == Orientation.Vertical) {
+                                       Width = Measure.Stretched;
+                                       return -1;
+                               } else if (RegisteredLayoutings.HasFlag (LayoutingType.Height))
+                                       return -1;
+                               else {
+                                       int dy = 0;
+                                       int largestChild = 0;
+
+                                       childrenRWLock.EnterReadLock();
+
+                                       foreach (Widget c in Children) {
+                                               if (!c.Visible)
+                                                       continue;
+                                               if (c.Height.IsRelativeToParent &&
+                                                   c.RegisteredLayoutings.HasFlag (LayoutingType.Height)) {
+                                                       childrenRWLock.ExitReadLock();
+                                                       return -1;
+                                               }
+                                               if (dy + c.Slot.Height > ClientRectangle.Height) {
+                                                       dy = 0;
+                                                       tmp += largestChild + Spacing;
+                                                       largestChild = c.Slot.Width;
+                                               } else if (largestChild < c.Slot.Width)
+                                                       largestChild = c.Slot.Width;
+
+                                               dy += c.Slot.Height + Spacing;
+                                       }
+
+                                       childrenRWLock.ExitReadLock ();
+
+                                       if (dy == 0)
+                                               tmp -= Spacing;
+                                       return tmp + largestChild + 2 * Margin;
+                               }
+                       } else if (Orientation == Orientation.Horizontal) {
+                               Height = Measure.Stretched;
+                               return -1;
+                       } else if (RegisteredLayoutings.HasFlag (LayoutingType.Width))
+                               return -1;
+                       else {
+                               int dx = 0;
+                               int tallestChild = 0;
+
+                               childrenRWLock.EnterReadLock();
+
+                               foreach (Widget c in Children) {
+                                       if (!c.Visible)
+                                               continue;
+                                       if (c.Width.IsRelativeToParent &&
+                                           c.RegisteredLayoutings.HasFlag (LayoutingType.Width)) {
+                                               childrenRWLock.ExitReadLock();
+                                               return -1;
+                                       }
+                                       if (dx + c.Slot.Width > ClientRectangle.Width) {
+                                               dx = 0;
+                                               tmp += tallestChild + Spacing;
+                                               tallestChild = c.Slot.Height;
+                                       } else if (tallestChild < c.Slot.Height)
+                                               tallestChild = c.Slot.Height;
+
+                                       dx += c.Slot.Width + Spacing;
+                               }
+
+                               childrenRWLock.ExitReadLock();
+
+                               if (dx == 0)
+                                       tmp -= Spacing;
+                               return tmp + tallestChild + 2 * Margin;
+                       }
+               }
+
+               public override bool UpdateLayout (LayoutingType layoutType)
+               {
+                       RegisteredLayoutings &= (~layoutType);
+
+                       if (layoutType == LayoutingType.ArrangeChildren) {
+                               if ((RegisteredLayoutings & LayoutingType.Sizing) != 0)
+                                       return false;
+
+                               ComputeChildrenPositions ();
+
+                               //if no layouting remains in queue for item, registre for redraw
+                               if (RegisteredLayoutings == LayoutingType.None && IsDirty)
+                                       IFace.EnqueueForRepaint (this);
+
+                               return true;
+                       }
+
+                       return base.UpdateLayout(layoutType);
+               }
+               public override void OnLayoutChanges (LayoutingType layoutType)
+               {
+                       #if DEBUG_LAYOUTING
+                       IFace.currentLQI.Slot = LastSlots;
+                       IFace.currentLQI.Slot = Slot;
+                       #endif
+                       switch (layoutType) {
+                       case LayoutingType.Width:
+                               foreach (Widget c in Children) {
+                                       if (c.Width.IsRelativeToParent)
+                                               c.RegisterForLayouting (LayoutingType.Width);
+                               }
+                               if (Height == Measure.Fit)
+                                       RegisterForLayouting (LayoutingType.Height);
+                               RegisterForLayouting (LayoutingType.X);
+                               break;
+                       case LayoutingType.Height:
+                               foreach (Widget c in Children) {
+                                       if (c.Height.IsRelativeToParent)
+                                               c.RegisterForLayouting (LayoutingType.Height);
+                               }
+                               if (Width == Measure.Fit)
+                                       RegisterForLayouting (LayoutingType.Width);
+                               RegisterForLayouting (LayoutingType.Y);
+                               break;
+                       default:
+                               return;
+                       }
+                       RegisterForLayouting (LayoutingType.ArrangeChildren);
+                       raiseLayoutChanged (new LayoutingEventArgs (layoutType));
+               }
+               #endregion
+       }
+}
+
diff --git a/Crow/src/Widgets/XmlIgnoreAttribute.cs b/Crow/src/Widgets/XmlIgnoreAttribute.cs
new file mode 100644 (file)
index 0000000..29e5bf6
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Expandable.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;
+
+namespace Crow
+{
+    public class XmlIgnoreAttribute : Attribute
+    {
+    }
+}
\ No newline at end of file