From 578341c3e4410b803b65a739f950b103f3f0a95c Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Wed, 10 Jun 2015 09:40:30 +0200 Subject: [PATCH] - expandables - events resolution stacking - Inlined template - xmlserialization debugging --- GOLib.csproj | 4 + Images/Icons/buttest4.svg | 141 +++++++++---------- Images/Icons/expandable.svg | 89 ++++++++++++ Templates/Expandable.goml | 10 ++ Tests/GOLIBTest_4.cs | 26 ++-- Tests/GOLIBTest_Expandable.cs | 55 ++++++++ Tests/Interfaces/test4.goml | 48 +++++-- Tests/Interfaces/testExpandable.goml | 13 ++ Tests/Tests.csproj | 7 +- src/CompilerServices/CompilerServices.cs | 32 +++-- src/GraphicObjects/AnalogMeter.cs | 2 +- src/GraphicObjects/Border.cs | 6 +- src/GraphicObjects/Button.cs | 6 +- src/GraphicObjects/Checkbox.cs | 19 ++- src/GraphicObjects/Container.cs | 165 ++--------------------- src/GraphicObjects/Expandable.cs | 144 ++++++++++++++++++++ src/GraphicObjects/GenericStack.cs | 16 +-- src/GraphicObjects/GraphicObject.cs | 9 +- src/GraphicObjects/Group.cs | 10 +- src/GraphicObjects/ListBox.cs | 8 +- src/GraphicObjects/PrivateContainer.cs | 165 +++++++++++++++++++++++ src/GraphicObjects/RadioButton.cs | 8 +- src/GraphicObjects/Scroller.cs | 14 +- src/GraphicObjects/Slider.cs | 2 +- src/GraphicObjects/Spinner.cs | 8 +- src/GraphicObjects/TemplatedControl.cs | 66 +++++---- src/Interface.cs | 77 +++++------ src/LayoutingQueueItem.cs | 2 +- 28 files changed, 780 insertions(+), 372 deletions(-) create mode 100644 Images/Icons/expandable.svg create mode 100755 Templates/Expandable.goml create mode 100644 Tests/GOLIBTest_Expandable.cs create mode 100755 Tests/Interfaces/testExpandable.goml mode change 100755 => 100644 src/GraphicObjects/Button.cs create mode 100644 src/GraphicObjects/Expandable.cs create mode 100644 src/GraphicObjects/PrivateContainer.cs diff --git a/GOLib.csproj b/GOLib.csproj index 15e126f0..28b47450 100644 --- a/GOLib.csproj +++ b/GOLib.csproj @@ -108,6 +108,8 @@ + + @@ -164,5 +166,7 @@ + + diff --git a/Images/Icons/buttest4.svg b/Images/Icons/buttest4.svg index 00880ad0..5bb1f0b9 100644 --- a/Images/Icons/buttest4.svg +++ b/Images/Icons/buttest4.svg @@ -10,9 +10,9 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="68.136505mm" - height="23.384127mm" - viewBox="0 0 241.42856 82.857141" + width="241.42857" + height="87.85714" + viewBox="0 0 241.42858 87.857136" id="svg6194" version="1.1" inkscape:version="0.91 r13725" @@ -21,29 +21,15 @@ id="defs6196"> - + id="linearGradient5895"> - + id="stop4179" /> + id="stop4181" /> + gradientTransform="translate(216.17265,-155.05841)" /> - - - + xlink:href="#linearGradient5895" + id="linearGradient4185" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(216.17265,-155.05841)" + x1="-94.577568" + y1="155.6501" + x2="-94.577568" + y2="239.49275" /> + inkscape:window-maximized="1" + units="px" /> @@ -121,52 +106,46 @@ image/svg+xml - + - - - - - - - - + id="normal"> + + + + + + diff --git a/Images/Icons/expandable.svg b/Images/Icons/expandable.svg new file mode 100644 index 00000000..43fb3ebc --- /dev/null +++ b/Images/Icons/expandable.svg @@ -0,0 +1,89 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/Templates/Expandable.goml b/Templates/Expandable.goml new file mode 100755 index 00000000..f2c2d098 --- /dev/null +++ b/Templates/Expandable.goml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/Tests/GOLIBTest_4.cs b/Tests/GOLIBTest_4.cs index 096d249e..796aac66 100644 --- a/Tests/GOLIBTest_4.cs +++ b/Tests/GOLIBTest_4.cs @@ -34,19 +34,31 @@ namespace test #region FPS static int _fps = 0; - public static int fps { + public int fps { get { return _fps; } set { + if (_fps == value) + return; + + int oldVal = _fps; _fps = value; - if (_fps > fpsMax) + + if (_fps > fpsMax) { fpsMax = _fps; - else if (_fps < fpsMin) + ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMax", fpsMax, _fps)); + } else if (_fps < fpsMin) { + ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMin", fpsMin, _fps)); fpsMin = _fps; - } + } + if (ValueChanged != null) + ValueChanged.Raise(this, new ValueChangeEventArgs ("fps", oldVal, _fps)); + + //ValueChanged.Raise (this, new ValueChangeEventArgs ("fps", oldVal, _fps)); + } } - public static int fpsMin = int.MaxValue; + public static int fpsMin = 0; public static int fpsMax = 0; static void resetFps () @@ -154,11 +166,9 @@ namespace test fps = (int)RenderFrequency; - labFps.Text = fps.ToString(); labUpdate.Text = this.updateTime.ElapsedMilliseconds.ToString() + " ms"; + if (frameCpt > 200) { - labFpsMin.Text = fpsMin.ToString(); - labFpsMax.Text = fpsMax.ToString(); resetFps (); frameCpt = 0; diff --git a/Tests/GOLIBTest_Expandable.cs b/Tests/GOLIBTest_Expandable.cs new file mode 100644 index 00000000..9da9b1ab --- /dev/null +++ b/Tests/GOLIBTest_Expandable.cs @@ -0,0 +1,55 @@ +#define MONO_CAIRO_DEBUG_DISPOSE + + +using System; +using System.Runtime.InteropServices; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using OpenTK.Input; + +using System.Diagnostics; + +//using GGL; +using go; +using System.Threading; + + +namespace test +{ + class GOLIBTest_Expandable : OpenTKGameWindow + { + public GOLIBTest_Expandable () + : base(1024, 600,"test") + {} + + Container g; + + protected override void OnLoad (EventArgs e) + { + base.OnLoad (e); + LoadInterface("Interfaces/testExpandable.goml", out g); + + } + protected override void OnRenderFrame (FrameEventArgs e) + { + GL.Clear (ClearBufferMask.ColorBufferBit); + base.OnRenderFrame (e); + SwapBuffers (); + } + + protected override void OnUpdateFrame (FrameEventArgs e) + { + base.OnUpdateFrame (e); + } + + [STAThread] + static void Main () + { + Console.WriteLine ("starting example"); + + using (GOLIBTest_Expandable win = new GOLIBTest_Expandable( )) { + win.Run (30.0); + } + } + } +} \ No newline at end of file diff --git a/Tests/Interfaces/test4.goml b/Tests/Interfaces/test4.goml index 914bce00..8b4f7691 100755 --- a/Tests/Interfaces/test4.goml +++ b/Tests/Interfaces/test4.goml @@ -13,7 +13,7 @@ WidgetSpacing="1" VerticalAlignment="Top"> - + - + + + + + + + + + + + + + + + + + + + + + - - - diff --git a/Tests/Interfaces/testExpandable.goml b/Tests/Interfaces/testExpandable.goml new file mode 100755 index 00000000..3349f61d --- /dev/null +++ b/Tests/Interfaces/testExpandable.goml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 4d2046bb..674e9325 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -8,11 +8,12 @@ Exe Tests Tests - test.GOLIBTest_Spinner + test.GOLIBTest_4 v4.5 ..\bin\$(configuration) obj\$(configuration) AnyCPU + false ..\bin\Debug @@ -55,6 +56,7 @@ + @@ -102,6 +104,9 @@ PreserveNewest + + PreserveNewest + diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index 6f00d36d..065c6924 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -163,20 +163,28 @@ namespace go MemberInfo miSrc = srcType.GetMember (binding.Value).FirstOrDefault(); //initialize target with actual value + object srcVal = null; + if (miSrc == null) + srcVal = _source;//if no member is provided for binding, source raw value is taken + else { + if (miSrc.MemberType == MemberTypes.Property) + srcVal = (miSrc as PropertyInfo).GetGetMethod ().Invoke (_source, null); + else if (miSrc.MemberType == MemberTypes.Field) + srcVal = (miSrc as FieldInfo).GetValue (_source); + else + throw new Exception ("unandled source member type for binding"); + } if (miDst.MemberType == MemberTypes.Property) { - if (miSrc == null)//if no member is provided for binding, source raw value is taken - (miDst as PropertyInfo).GetSetMethod ().Invoke (binding.Source, new object[] { _source }); - else if (miSrc.MemberType == MemberTypes.Property) - (miDst as PropertyInfo).GetSetMethod ().Invoke (binding.Source, new object[] { (miSrc as PropertyInfo).GetGetMethod ().Invoke (_source, null) }); - else if (miSrc.MemberType == MemberTypes.Field) - (miDst as PropertyInfo).GetSetMethod ().Invoke (binding.Source, new object[] { (miSrc as FieldInfo).GetValue (_source) }); + PropertyInfo piDst = miDst as PropertyInfo; + //TODO: handle other dest type conversions + if (piDst.PropertyType == typeof(string)) + srcVal = srcVal.ToString (); + piDst.GetSetMethod ().Invoke (binding.Source, new object[] { srcVal }); } else if (miDst.MemberType == MemberTypes.Field) { - if (miSrc == null)//if no member is provided for binding, source raw value is taken - (miDst as FieldInfo).SetValue (binding.Source, _source ); - else if (miSrc.MemberType == MemberTypes.Property) - (miDst as FieldInfo).SetValue (binding.Source, (miSrc as PropertyInfo).GetGetMethod ().Invoke (_source, null)); - else if (miSrc.MemberType == MemberTypes.Field) - (miDst as FieldInfo).SetValue (binding.Source, (miSrc as FieldInfo).GetValue (_source)); + FieldInfo fiDst = miDst as FieldInfo; + if (fiDst.FieldType == typeof(string)) + srcVal = srcVal.ToString (); + fiDst.SetValue (binding.Source, srcVal ); }else throw new Exception("unandled destination member type for binding"); diff --git a/src/GraphicObjects/AnalogMeter.cs b/src/GraphicObjects/AnalogMeter.cs index e487189d..dd248cee 100644 --- a/src/GraphicObjects/AnalogMeter.cs +++ b/src/GraphicObjects/AnalogMeter.cs @@ -18,7 +18,7 @@ namespace go #region implemented abstract members of TemplatedControl - protected override void loadTemplate () + protected override void loadTemplate (GraphicObject template = null) { throw new NotImplementedException (); } diff --git a/src/GraphicObjects/Border.cs b/src/GraphicObjects/Border.cs index e2451582..352b626a 100644 --- a/src/GraphicObjects/Border.cs +++ b/src/GraphicObjects/Border.cs @@ -47,11 +47,11 @@ namespace go { Size raw = Bounds.Size; - if (child != null) { + if (Child != null) { if (Bounds.Width < 0) - raw.Width = child.Slot.Width + 2 * (Margin+BorderWidth); + raw.Width = Child.Slot.Width + 2 * (Margin+BorderWidth); if (Bounds.Height < 0) - raw.Height = child.Slot.Height + 2 * (Margin+BorderWidth); + raw.Height = Child.Slot.Height + 2 * (Margin+BorderWidth); } return raw; diff --git a/src/GraphicObjects/Button.cs b/src/GraphicObjects/Button.cs old mode 100755 new mode 100644 index fcbdecd8..c092ac1e --- a/src/GraphicObjects/Button.cs +++ b/src/GraphicObjects/Button.cs @@ -63,14 +63,14 @@ namespace go public string Text { get { - Label l = child as Label; + Label l = Child as Label; return l == null ? "" : l.Text; } set { - Label l = child as Label; + Label l = Child as Label; if (l == null) - this.setChild(new Label (value) + this.SetChild(new Label (value) { TextAlignment = Alignment.Center, Foreground = Color.Black diff --git a/src/GraphicObjects/Checkbox.cs b/src/GraphicObjects/Checkbox.cs index 07be76c5..d36f1266 100644 --- a/src/GraphicObjects/Checkbox.cs +++ b/src/GraphicObjects/Checkbox.cs @@ -25,9 +25,13 @@ namespace go { } - protected override void loadTemplate() - { - this.setChild (Interface.Load ("#go.Templates.Checkbox.goml")); + protected override void loadTemplate(GraphicObject template = null) + { + if (template == null) + this.SetChild (Interface.Load ("#go.Templates.Checkbox.goml", this)); + else + this.SetChild (template); + _caption = this.child.FindByName ("Caption") as Label; _image = this.child.FindByName ("Image") as Image; _image.SvgSub = "unchecked"; @@ -36,8 +40,10 @@ namespace go [XmlAttributeAttribute()][DefaultValue("Checkbox")] public string Caption { - get { return _caption.Text; } + get { return _caption == null ? "" : _caption.Text; } set { + if (_caption == null) + return; _caption.Text = value; } } @@ -64,5 +70,10 @@ namespace go IsChecked = !IsChecked; base.onMouseClick (sender, e); } + + public override void ReadXml (System.Xml.XmlReader reader) + { + base.ReadXml (reader); + } } } diff --git a/src/GraphicObjects/Container.cs b/src/GraphicObjects/Container.cs index 66e3b9e4..c0ac00c6 100644 --- a/src/GraphicObjects/Container.cs +++ b/src/GraphicObjects/Container.cs @@ -7,7 +7,7 @@ using System.Linq; namespace go { - public class Container : GraphicObject, IXmlSerializable + public class Container : PrivateContainer, IXmlSerializable { #region CTOR public Container() @@ -20,151 +20,16 @@ namespace go } #endregion - public GraphicObject child; - - public T setChild(T _child) - { - - if (child != null) { - this.RegisterForLayouting ((int)LayoutingType.Sizing); - child.Parent = null; - } - - child = _child as GraphicObject; - - if (child != null) { - child.Parent = this; - child.RegisterForLayouting ((int)LayoutingType.Sizing); - } - - return (T)_child; - } - - #region GraphicObject Overrides - //check if not causing problems - [XmlAttributeAttribute()][DefaultValue(true)] - public override bool Focusable - { - get { return base.Focusable; } - set { base.Focusable = value; } - } - - public override GraphicObject FindByName (string nameToFind) - { - if (Name == nameToFind) - return this; - - return child == null ? null : child.FindByName (nameToFind); - } - public override bool Contains (GraphicObject goToFind) - { - return child == goToFind ? true : - child == null ? false : child.Contains(goToFind); - } - protected override Size measureRawSize () - { - return child == null ? Bounds.Size : new Size(child.Slot.Width + 2 * Margin, child.Slot.Height + 2 * (Margin)); + [XmlIgnore] + public GraphicObject Child { + get { return child; } + set { child = value; } } - - protected override void OnLayoutChanges (LayoutingType layoutType) + public T SetChild (T _child) { - switch (layoutType) { - case LayoutingType.Width: - base.OnLayoutChanges (layoutType); - if (child != null) { - if (child.getBounds ().Width == 0) - child.RegisterForLayouting ((int)LayoutingType.Width); - else - child.RegisterForLayouting ((int)LayoutingType.X); - } - break; - case LayoutingType.Height: - base.OnLayoutChanges (layoutType); - if (child != null) { - if (child.getBounds ().Height == 0) - child.RegisterForLayouting ((int)LayoutingType.Height); - else - child.RegisterForLayouting ((int)LayoutingType.Y); - } - break; - } + return base.SetChild (_child); } -// public override void RegisterForLayouting(int layoutType) -// { -// Interface.LayoutingQueue.RemoveAll (lq => lq.GraphicObject == this && (layoutType & (int)lq.LayoutType) > 0); -// -// if ((layoutType & (int)LayoutingType.Width) > 0) { -// if (Bounds.Width == 0) //stretch in parent -// Interface.LayoutingQueue.EnqueueAfterParentSizing (LayoutingType.Width, this); -// else //fit ou fixed -// Interface.LayoutingQueue.Enqueue (LayoutingType.Width, this); -// } -// -// if ((layoutType & (int)LayoutingType.Height) > 0) { -// if (Bounds.Height == 0) //stretch in parent -// Interface.LayoutingQueue.EnqueueAfterParentSizing (LayoutingType.Height, this); -// else//fit ou fixed -// Interface.LayoutingQueue.Enqueue (LayoutingType.Height, this); -// } -// -// if ((layoutType & (int)LayoutingType.X) > 0) -// //for x positionning, sizing of parent and this have to be done -// Interface.LayoutingQueue.EnqueueAfterThisAndParentSizing (LayoutingType.X, this); -// -// if ((layoutType & (int)LayoutingType.Y) > 0) -// //for x positionning, sizing of parent and this have to be done -// Interface.LayoutingQueue.EnqueueAfterThisAndParentSizing (LayoutingType.Y, this); -// -// } - - public override Rectangle ContextCoordinates (Rectangle r) - { - return - Parent.ContextCoordinates(r) + getSlot().Position + ClientRectangle.Position; - - } - public override void Paint(ref Cairo.Context ctx, Rectangles clip = null) - { - if (!Visible)//check if necessary?? - return; - - ctx.Save(); - -// ctx.Rectangle(ContextCoordinates(Slot)); -// ctx.Clip(); -// - if (clip != null) - clip.clip(ctx); - - base.Paint(ref ctx, clip); - - //clip to client zone - ctx.Rectangle(Parent.ContextCoordinates(ClientRectangle + Slot.Position)); - ctx.Clip(); - -// if (clip != null) -// clip.Rebase(this); - - if (child != null) - child.Paint(ref ctx, clip); - - ctx.Restore(); - } - #endregion - - #region Mouse handling - public override void onMouseMove (object sender, MouseMoveEventArgs e) - { - base.onMouseMove (sender, e); - - if (child != null) - if (child.MouseIsIn (e.Position)) - child.onMouseMove (sender, e); - - } - #endregion - #region IXmlSerializable public override System.Xml.Schema.XmlSchema GetSchema() @@ -173,8 +38,10 @@ namespace go } public override void ReadXml(System.Xml.XmlReader reader) { + //only read attributes in GraphicObject IXmlReader implementation base.ReadXml(reader); + using (System.Xml.XmlReader subTree = reader.ReadSubtree()) { subTree.Read(); //skip current node @@ -188,24 +55,20 @@ namespace go (go as IXmlSerializable).ReadXml(subTree); - setChild(go); - - subTree.Read(); - - if (!subTree.IsStartElement()) - return; + SetChild(go); + subTree.Read();//closing tag } } public override void WriteXml(System.Xml.XmlWriter writer) { base.WriteXml(writer); - if (child == null) + if (Child == null) return; - writer.WriteStartElement(child.GetType().Name); - (child as IXmlSerializable).WriteXml(writer); + writer.WriteStartElement(Child.GetType().Name); + (Child as IXmlSerializable).WriteXml(writer); writer.WriteEndElement(); } diff --git a/src/GraphicObjects/Expandable.cs b/src/GraphicObjects/Expandable.cs new file mode 100644 index 00000000..e3274ca0 --- /dev/null +++ b/src/GraphicObjects/Expandable.cs @@ -0,0 +1,144 @@ +using System; + + +using System.Collections.Generic; +using System.Linq; +using System.Text; +//using OpenTK.Graphics.OpenGL; + +using Cairo; + +using winColors = System.Drawing.Color; +using System.Diagnostics; +using System.Xml.Serialization; +using OpenTK.Input; +using System.ComponentModel; +using System.Xml; +using System.IO; + +namespace go +{ + public class Expandable : TemplatedControl + { + bool _isExpanded; + Label _caption; + + public Container Content; + + public event EventHandler Expand; + public event EventHandler Collapse; + + public Expandable() : base() + { + } + + protected override void loadTemplate(GraphicObject template = null) + { + if (template == null) + this.SetChild (Interface.Load ("#go.Templates.Expandable.goml",this)); + else + this.SetChild (template); + + _caption = this.child.FindByName ("Caption") as Label; + Content = this.child.FindByName ("Content") as Container; + } + + + [XmlAttributeAttribute()][DefaultValue("Expandable")] + public string Title { + get { return _caption.Text; } + set { + if (_caption == null) + return; + _caption.Text = value; + } + } + + [XmlAttributeAttribute()][DefaultValue(false)] + public bool IsExpanded + { + get { return _isExpanded; } + set + { + if (value == _isExpanded) + return; + + _isExpanded = value; + + if (_isExpanded) + onExpand (this, null); + else + onCollapse (this, null); + + registerForGraphicUpdate(); + } + } + + public virtual void onExpand(object sender, EventArgs e) + { + Content.Visible = true; + Expand.Raise (this, e); + } + public virtual void onCollapse(object sender, EventArgs e) + { + Content.Visible = false; + Collapse.Raise (this, e); + } + + public override void onMouseClick (object sender, MouseButtonEventArgs e) + { + IsExpanded = !IsExpanded; + base.onMouseClick (sender, e); + } + + public override void ReadXml(System.Xml.XmlReader reader) + { + using (System.Xml.XmlReader subTree = reader.ReadSubtree ()) { + subTree.Read (); + string tmp = subTree.ReadOuterXml (); + + //seek for template tag + using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { + xr.Read (); + base.ReadXml (xr); + } + //process content + using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { + xr.Read (); //skip current node + + while (!xr.EOF) { + xr.Read (); //read first child + + if (!xr.IsStartElement ()) + continue; + if (xr.Name == "Template") + continue; + + Type t = Type.GetType ("go." + xr.Name); + GraphicObject go = (GraphicObject)Activator.CreateInstance (t); + + (go as IXmlSerializable).ReadXml (xr); + + Content.SetChild (go); + + xr.Read (); //closing tag + } + + } + } + } + public override void WriteXml(System.Xml.XmlWriter writer) + { + base.WriteXml(writer); + + if (Content == null) + return; + if (Content.Child == null) + return; + //TODO: if template is not the default one, we have to save it + writer.WriteStartElement(Content.Child.GetType().Name); + (Content.Child as IXmlSerializable).WriteXml(writer); + writer.WriteEndElement(); + } + } +} diff --git a/src/GraphicObjects/GenericStack.cs b/src/GraphicObjects/GenericStack.cs index 63a70ad3..0b37f07b 100644 --- a/src/GraphicObjects/GenericStack.cs +++ b/src/GraphicObjects/GenericStack.cs @@ -66,14 +66,14 @@ namespace go Size tmp = new Size (); if (Orientation == Orientation.Horizontal) { - foreach (GraphicObject c in Children) { + foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { tmp.Width += c.Slot.Width + Spacing; tmp.Height = Math.Max (tmp.Height, c.Slot.Bottom); } if (tmp.Width > 0) tmp.Width -= Spacing; } else { - foreach (GraphicObject c in Children) { + foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { tmp.Width = Math.Max (tmp.Width, c.Slot.Right); tmp.Height += c.Slot.Height + Spacing; } @@ -90,13 +90,13 @@ namespace go { int d = 0; if (Orientation == Orientation.Horizontal) { - foreach (GraphicObject c in Children) { + foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { c.Slot.X = d; d += c.Slot.Width + Spacing; c.RegisterForLayouting ((int)LayoutingType.Y); } } else { - foreach (GraphicObject c in Children) { + foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { c.Slot.Y = d; d += c.Slot.Height + Spacing; c.RegisterForLayouting ((int)LayoutingType.X); @@ -119,11 +119,11 @@ namespace go //this child will occupy remaining space if (Orientation == Orientation.Horizontal) { if (Width >= 0) { - GraphicObject[] gobjs = Children.Where (c => c.Width == 0).ToArray(); + GraphicObject[] gobjs = Children.Where (c => c.Width == 0 && c.Visible).ToArray(); if (gobjs.Length > 1) throw new Exception ("Only one child in stack may have size to stretched"); else if (gobjs.Length == 1) { - int sz = Children.Except (gobjs).Sum (g => g.Slot.Width); + int sz = Children.Where(ch=>ch.Visible).Except (gobjs).Sum (g => g.Slot.Width); if (sz < Slot.Width) { gobjs [0].Slot.Width = Slot.Width - sz - Spacing; int idx = Children.IndexOf (gobjs [0]); @@ -139,11 +139,11 @@ namespace go } } else { if (Height >= 0) { - GraphicObject[] gobjs = Children.Where (c => c.Height == 0).ToArray(); + GraphicObject[] gobjs = Children.Where(ch=>ch.Visible).Where (c => c.Height == 0).ToArray(); if (gobjs.Length > 1) throw new Exception ("Only one child in stack may have size to stretched"); else if (gobjs.Length == 1) { - int sz = Children.Except (gobjs).Sum (g => g.Slot.Height); + int sz = Children.Where(ch=>ch.Visible).Except (gobjs).Sum (g => g.Slot.Height); if (sz < Slot.Height) { gobjs [0].Slot.Height = Slot.Height - sz; int idx = Children.IndexOf (gobjs [0]); diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index 9e55d1cf..8098f863 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -238,13 +238,16 @@ namespace go _isVisible = value; + if (TopContainer == null) + return; //add slot to clipping to redraw TopContainer.gobjsToRedraw.Add (this); //ensure main win doesn't keep hidden childrens ref if (this.Contains (TopContainer.hoverWidget)) TopContainer.hoverWidget = null; -// if (Parent != null) + if (Parent is GenericStack) + Parent.RegisterForLayouting ((int)LayoutingType.Sizing | (int)LayoutingType.PositionChildren); // Parent.InvalidateLayout (); //else // registerForRedraw(); @@ -666,7 +669,6 @@ namespace go } #region IXmlSerializable - public virtual System.Xml.Schema.XmlSchema GetSchema () { return null; @@ -802,7 +804,6 @@ namespace go } } - public virtual void WriteXml (System.Xml.XmlWriter writer) { foreach (PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { @@ -889,7 +890,7 @@ namespace go } } } + #endregion - #endregion } } diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index 42da7983..f1620a2a 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -109,7 +109,7 @@ namespace go { Size tmp = new Size (); - foreach (GraphicObject c in Children) { + foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { tmp.Width = Math.Max (tmp.Width, c.Slot.Right); tmp.Height = Math.Max (tmp.Height, c.Slot.Bottom); } @@ -129,14 +129,14 @@ namespace go case LayoutingType.Width: if (Width < 0) { int crw = ClientRectangle.Width; - foreach (GraphicObject c in Children.Where(ch => ch.Slot.Width != crw)) + foreach (GraphicObject c in Children.Where(ch => ch.Slot.Width != crw && ch.Visible)) c.RegisterForLayouting ((int)LayoutingType.X); } break; case LayoutingType.Height: if (Height < 0) { int crh = ClientRectangle.Height; - foreach (GraphicObject c in Children.Where(ch => ch.Slot.Height != crh)) + foreach (GraphicObject c in Children.Where(ch => ch.Slot.Height != crh && ch.Visible)) c.RegisterForLayouting ((int)LayoutingType.Y); } break; @@ -154,7 +154,7 @@ namespace go CairoHelpers.CairoRectangle(gr,rBack,CornerRadius); gr.Fill (); - foreach (GraphicObject g in Children) { + foreach (GraphicObject g in Children.Where(ch=>ch.Visible)) { g.Paint (ref gr); } } @@ -197,7 +197,7 @@ namespace go #if DEBUG_CLIP_RECTANGLE clip.stroke (gr, Color.Amaranth.AdjustAlpha (0.8)); #endif - foreach (GraphicObject c in Children) { + foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { Rectangles childClip = clip.intersectingRects (ContextCoordinates(c.Slot)); if (!c.DrawingIsValid || childClip.count > 0) c.Paint (ref gr,childClip);//, localClip); diff --git a/src/GraphicObjects/ListBox.cs b/src/GraphicObjects/ListBox.cs index 1f0ccf5e..ce6db79b 100644 --- a/src/GraphicObjects/ListBox.cs +++ b/src/GraphicObjects/ListBox.cs @@ -34,9 +34,13 @@ namespace go } #region implemented abstract members of TemplatedControl - protected override void loadTemplate () + protected override void loadTemplate (GraphicObject template = null) { - this.setChild (Interface.Load ("#go.Templates.Listbox.goml")); + if (template == null) + this.SetChild (Interface.Load ("#go.Templates.Listbox.goml")); + else + this.SetChild (template); + _list = this.child.FindByName ("List") as Group; } #endregion diff --git a/src/GraphicObjects/PrivateContainer.cs b/src/GraphicObjects/PrivateContainer.cs new file mode 100644 index 00000000..23d65c20 --- /dev/null +++ b/src/GraphicObjects/PrivateContainer.cs @@ -0,0 +1,165 @@ +// +// PrivateContainer.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2015 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Xml.Serialization; +using System.ComponentModel; +using OpenTK.Input; + +namespace go +{ + /// + /// Implement drawing and layouting for a single child, but + /// does not implement IXmlSerialisation 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 + /// + public class PrivateContainer : GraphicObject + { + #region CTOR + public PrivateContainer() + : base() + { + } + public PrivateContainer(Rectangle _bounds) + : base(_bounds) + { + } + #endregion + + protected GraphicObject child; + + protected virtual T SetChild(T _child) + { + + if (child != null) { + this.RegisterForLayouting ((int)LayoutingType.Sizing); + child.Parent = null; + } + + child = _child as GraphicObject; + + if (child != null) { + child.Parent = this; + child.RegisterForLayouting ((int)LayoutingType.Sizing); + } + + return (T)_child; + } + + #region GraphicObject Overrides + //check if not causing problems + [XmlAttributeAttribute()][DefaultValue(true)] + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + + public override GraphicObject FindByName (string nameToFind) + { + if (Name == nameToFind) + return this; + + return child == null ? null : child.FindByName (nameToFind); + } + public override bool Contains (GraphicObject goToFind) + { + return child == goToFind ? true : + child == null ? false : child.Contains(goToFind); + } + protected override Size measureRawSize () + { + return child == null ? Bounds.Size : new Size(child.Slot.Width + 2 * Margin, child.Slot.Height + 2 * (Margin)); + } + + protected override void OnLayoutChanges (LayoutingType layoutType) + { + switch (layoutType) { + case LayoutingType.Width: + base.OnLayoutChanges (layoutType); + if (child != null) { + if (child.getBounds ().Width == 0) + child.RegisterForLayouting ((int)LayoutingType.Width); + else + child.RegisterForLayouting ((int)LayoutingType.X); + } + break; + case LayoutingType.Height: + base.OnLayoutChanges (layoutType); + if (child != null) { + if (child.getBounds ().Height == 0) + child.RegisterForLayouting ((int)LayoutingType.Height); + else + child.RegisterForLayouting ((int)LayoutingType.Y); + } + break; + } + } + + public override Rectangle ContextCoordinates (Rectangle r) + { + return + Parent.ContextCoordinates(r) + getSlot().Position + ClientRectangle.Position; + } + public override void Paint(ref Cairo.Context ctx, Rectangles clip = null) + { + if (!Visible)//check if necessary?? + return; + + ctx.Save(); + + // ctx.Rectangle(ContextCoordinates(Slot)); + // ctx.Clip(); + // + if (clip != null) + clip.clip(ctx); + + base.Paint(ref ctx, clip); + + //clip to client zone + ctx.Rectangle(Parent.ContextCoordinates(ClientRectangle + Slot.Position)); + ctx.Clip(); + + // if (clip != null) + // clip.Rebase(this); + + if (child != null) + child.Paint(ref ctx, clip); + + ctx.Restore(); + } + #endregion + + #region Mouse handling + public override void onMouseMove (object sender, MouseMoveEventArgs e) + { + base.onMouseMove (sender, e); + + if (child != null) + if (child.MouseIsIn (e.Position)) + child.onMouseMove (sender, e); + + } + #endregion + } +} + diff --git a/src/GraphicObjects/RadioButton.cs b/src/GraphicObjects/RadioButton.cs index 9d6990db..71911d68 100644 --- a/src/GraphicObjects/RadioButton.cs +++ b/src/GraphicObjects/RadioButton.cs @@ -25,9 +25,13 @@ namespace go { } - protected override void loadTemplate() + protected override void loadTemplate(GraphicObject template = null) { - this.setChild (Interface.Load ("#go.Templates.RadioButton.goml")); + if (template == null) + this.SetChild (Interface.Load ("#go.Templates.RadioButton.goml")); + else + this.SetChild (template); + _caption = this.child.FindByName ("Caption") as Label; _image = this.child.FindByName ("Image") as Image; _image.SvgSub = "unchecked"; diff --git a/src/GraphicObjects/Scroller.cs b/src/GraphicObjects/Scroller.cs index fa323f0d..0b0eaae7 100644 --- a/src/GraphicObjects/Scroller.cs +++ b/src/GraphicObjects/Scroller.cs @@ -66,7 +66,7 @@ namespace go // if (MouseWheelChanged!=null) // MouseWheelChanged (this, e); - if (child == null) + if (Child == null) return; if (VerticalScrolling ) @@ -78,8 +78,8 @@ namespace go if (scrollY > 0) scrollY = 0; - else if (scrollY < -child.Slot.Height + ClientRectangle.Height) - scrollY = -child.Slot.Height + ClientRectangle.Height; + else if (scrollY < -Child.Slot.Height + ClientRectangle.Height) + scrollY = -Child.Slot.Height + ClientRectangle.Height; } if (HorizontalScrolling ) @@ -91,8 +91,8 @@ namespace go if (scrollX > 0) scrollX = 0; - else if (scrollX < -child.Slot.Width + ClientRectangle.Width) - scrollX = -child.Slot.Width + ClientRectangle.Width; + else if (scrollX < -Child.Slot.Width + ClientRectangle.Width) + scrollX = -Child.Slot.Width + ClientRectangle.Width; } @@ -141,8 +141,8 @@ namespace go // if (clip != null) // clip.Rebase(this); - if (child != null) - child.Paint(ref ctx, clip); + if (Child != null) + Child.Paint(ref ctx, clip); ctx.Restore(); } diff --git a/src/GraphicObjects/Slider.cs b/src/GraphicObjects/Slider.cs index 8c314377..7a5623f8 100644 --- a/src/GraphicObjects/Slider.cs +++ b/src/GraphicObjects/Slider.cs @@ -22,7 +22,7 @@ namespace go #region implemented abstract members of TemplatedControl - protected override void loadTemplate () + protected override void loadTemplate (GraphicObject template = null) { } diff --git a/src/GraphicObjects/Spinner.cs b/src/GraphicObjects/Spinner.cs index 4706effe..4bd3a723 100644 --- a/src/GraphicObjects/Spinner.cs +++ b/src/GraphicObjects/Spinner.cs @@ -40,9 +40,13 @@ namespace go #region implemented abstract members of TemplatedControl - protected override void loadTemplate () + protected override void loadTemplate (GraphicObject template = null) { - this.setChild (Interface.Load ("#go.Templates.Spinner.goml", this)); + if (template == null) + this.SetChild (Interface.Load ("#go.Templates.Spinner.goml", this)); + else + this.SetChild (template); + labCpt = this.child.FindByName ("labCpt") as Label; } diff --git a/src/GraphicObjects/TemplatedControl.cs b/src/GraphicObjects/TemplatedControl.cs index df843076..75d5b54f 100644 --- a/src/GraphicObjects/TemplatedControl.cs +++ b/src/GraphicObjects/TemplatedControl.cs @@ -21,10 +21,12 @@ using System; using System.Xml.Serialization; using System.ComponentModel; +using System.IO; +using System.Xml; namespace go { - public abstract class TemplatedControl : Container, IXmlSerializable + public abstract class TemplatedControl : PrivateContainer, IXmlSerializable { public TemplatedControl () : base() { @@ -38,11 +40,12 @@ namespace go // } - protected abstract void loadTemplate(); + protected abstract void loadTemplate(GraphicObject template = null); protected override void loadDefaultValues () { - loadTemplate (); + if (child == null)//trigger loading of default template if child is empty + loadTemplate (); base.loadDefaultValues (); this.Focusable = true; } @@ -61,29 +64,42 @@ namespace go } public override void ReadXml(System.Xml.XmlReader reader) { - base.ReadXml(reader); + using (System.Xml.XmlReader subTree = reader.ReadSubtree()) + { + subTree.Read (); + string tmp = subTree.ReadOuterXml (); -// using (System.Xml.XmlReader subTree = reader.ReadSubtree()) -// { -// subTree.Read(); //skip current node -// subTree.Read(); //read first child -// -// if (!subTree.IsStartElement()) -// return; -// -// Type t = Type.GetType("go." + subTree.Name); -// GraphicObject go = (GraphicObject)Activator.CreateInstance(t); -// -// (go as IXmlSerializable).ReadXml(subTree); -// -// setChild(go); -// -// subTree.Read(); -// -// if (!subTree.IsStartElement()) -// return; -// -// } + //seek for template tag first + using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { + //load template first if inlined + + xr.Read (); //skip current node + + while (!xr.EOF) { + xr.Read (); //read first child + if (!xr.IsStartElement ()) + continue; + if (xr.Name == "Template") { + xr.Read (); + + Type t = Type.GetType ("go." + xr.Name); + GraphicObject go = (GraphicObject)Activator.CreateInstance (t); + (go as IXmlSerializable).ReadXml (xr); + + loadTemplate (go); + + xr.Read ();//go close tag + xr.Read ();//Template close tag + } else { + xr.ReadInnerXml (); + } + } + } + using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { + xr.Read (); + base.ReadXml(xr); + } + } } public override void WriteXml(System.Xml.XmlWriter writer) { diff --git a/src/Interface.cs b/src/Interface.cs index 2b80564f..29e276c0 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -45,9 +45,14 @@ namespace go #region Load/Save - internal static List EventsToResolve; + internal static Stack> EventsResolutionStack = new Stack>(); + internal static List EventsToResolve + { + get { return EventsResolutionStack.Peek ();} + } internal static List Bindings; + public static void Save(string file, T graphicObject) { XmlSerializerNamespaces xn = new XmlSerializerNamespaces(); @@ -105,7 +110,7 @@ namespace go { //result = (T)(Load (file, hostClass) as object); - EventsToResolve = new List(); + EventsResolutionStack.Push(new List()); Bindings = new List (); XmlSerializerNamespaces xn = new XmlSerializerNamespaces(); @@ -120,27 +125,8 @@ namespace go if (hostClass == null) return; - foreach (DynAttribute es in EventsToResolve) - { - if (string.IsNullOrEmpty(es.Value)) - continue; + resolveEvents (hostClass); - if (es.Value.StartsWith ("{")) { - CompilerServices.CompileEventSource (es); - } else { - MethodInfo mi = hostClass.GetType ().GetMethod (es.Value, BindingFlags.NonPublic | BindingFlags.Public - | BindingFlags.Instance); - - if (mi == null) { - Debug.WriteLine ("Handler Method not found: " + es.Value); - continue; - } - - FieldInfo fi = CompilerServices.getEventHandlerField (es.Source.GetType (), es.MemberName); - Delegate del = Delegate.CreateDelegate(fi.FieldType, hostClass, mi); - fi.SetValue(es.Source, del); - } - } while (Bindings.Count > 0) { DynAttribute binding = Bindings [0]; Bindings.RemoveAt (0); @@ -157,10 +143,11 @@ namespace go // } // Bindings.Clear (); } + public static GraphicObject Load(Stream stream, Type type, object hostClass = null) { GraphicObject result; - EventsToResolve = new List(); + EventsResolutionStack.Push(new List()); XmlSerializerNamespaces xn = new XmlSerializerNamespaces(); xn.Add("", ""); @@ -171,6 +158,31 @@ namespace go if (hostClass == null) return result; + resolveEvents (hostClass); + + while (Bindings.Count > 0) { + DynAttribute binding = Bindings [0]; + Bindings.RemoveAt (0); + CompilerServices.ResolveBinding (binding, hostClass); + } + +// foreach (DynAttribute binding in Bindings) { +// // Type tSource = binding.Source.GetType (); +// // if (!tSource.GetInterfaces ().Any (i => i.Name == "IValueChange")){ +// // Debug.WriteLine ("Binding source does not implement IValueChange."); +// // continue; +// // } +// //MemberInfo mi = binding.Source.GetType ().GetMember (binding.MemberName); +// CompilerServices.CreateBinding (binding, hostClass); +// } +// Bindings.Clear (); + + + return result; + } + + static void resolveEvents(object hostClass) + { foreach (DynAttribute es in EventsToResolve) { if (string.IsNullOrEmpty(es.Value)) @@ -192,25 +204,8 @@ namespace go fi.SetValue(es.Source, del); } } - while (Bindings.Count > 0) { - DynAttribute binding = Bindings [0]; - Bindings.RemoveAt (0); - CompilerServices.ResolveBinding (binding, hostClass); - } - -// foreach (DynAttribute binding in Bindings) { -// // Type tSource = binding.Source.GetType (); -// // if (!tSource.GetInterfaces ().Any (i => i.Name == "IValueChange")){ -// // Debug.WriteLine ("Binding source does not implement IValueChange."); -// // continue; -// // } -// //MemberInfo mi = binding.Source.GetType ().GetMember (binding.MemberName); -// CompilerServices.CreateBinding (binding, hostClass); -// } -// Bindings.Clear (); - return result; + EventsResolutionStack.Pop(); } - #endregion } } diff --git a/src/LayoutingQueueItem.cs b/src/LayoutingQueueItem.cs index e1d21792..b028fb83 100644 --- a/src/LayoutingQueueItem.cs +++ b/src/LayoutingQueueItem.cs @@ -47,7 +47,7 @@ namespace go } public void ProcessLayouting() { - Debug.WriteLine ("Layouting => " + this.ToString ()); + //Debug.WriteLine ("Layouting => " + this.ToString ()); try { GraphicObject.UpdateLayout (LayoutType); } catch (Exception ex) { -- 2.47.3