From 41b76ea576cdece6c5a2f1feb936dfb4a2a9854a Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Thu, 17 Sep 2015 18:30:01 +0200 Subject: [PATCH] Combobox --- GOLib.csproj | 7 +- Templates/ComboListOverlay.goml | 6 - Templates/Combobox.goml | 10 + Templates/ComboboxOverlay.goml | 7 + Tests/GOLIBTest_Listbox.cs | 15 +- Tests/GOLIBTests.cs | 9 + Tests/Interfaces/testCombobox.goml | 2 + Tests/Tests.csproj | 3 + src/GraphicObjects/Combobox.cs | 293 +++++++++++++++++++++++++ src/GraphicObjects/GraphicObject.cs | 2 +- src/GraphicObjects/ListBox.cs | 94 ++++++-- src/GraphicObjects/TemplatedControl.cs | 55 +++-- src/Interface.cs | 2 +- src/SelectionChangeEventArgs.cs | 16 ++ 14 files changed, 461 insertions(+), 60 deletions(-) delete mode 100755 Templates/ComboListOverlay.goml create mode 100755 Templates/Combobox.goml create mode 100755 Templates/ComboboxOverlay.goml create mode 100755 Tests/Interfaces/testCombobox.goml create mode 100644 src/GraphicObjects/Combobox.cs create mode 100644 src/SelectionChangeEventArgs.cs diff --git a/GOLib.csproj b/GOLib.csproj index e2e9dfa5..1c5d4263 100644 --- a/GOLib.csproj +++ b/GOLib.csproj @@ -116,7 +116,6 @@ - @@ -124,6 +123,9 @@ + + + @@ -177,7 +179,6 @@ - @@ -202,6 +203,8 @@ + + diff --git a/Templates/ComboListOverlay.goml b/Templates/ComboListOverlay.goml deleted file mode 100755 index 65bac62b..00000000 --- a/Templates/ComboListOverlay.goml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Templates/Combobox.goml b/Templates/Combobox.goml new file mode 100755 index 00000000..21824049 --- /dev/null +++ b/Templates/Combobox.goml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/Templates/ComboboxOverlay.goml b/Templates/ComboboxOverlay.goml new file mode 100755 index 00000000..349be301 --- /dev/null +++ b/Templates/ComboboxOverlay.goml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/Tests/GOLIBTest_Listbox.cs b/Tests/GOLIBTest_Listbox.cs index 0189e3f6..1c19338e 100644 --- a/Tests/GOLIBTest_Listbox.cs +++ b/Tests/GOLIBTest_Listbox.cs @@ -64,19 +64,18 @@ namespace test // new ClsItem("string 2"), // new ClsItem("string 3") // }); - public List TestList; -// string[] TestList = new string[] -// { -// "string 1", -// "string 2", -// "string 3" -// }; + public List TestList = new List( new string[] + { + "string 1", + "string 2", + "string 3" + }); protected override void OnLoad (EventArgs e) { base.OnLoad (e); - TestList = Directory.GetFileSystemEntries("/mnt/data/MagicCardDataBase/a/", "*.txt",SearchOption.AllDirectories).ToList(); + //TestList = Directory.GetFileSystemEntries("/mnt/data/MagicCardDataBase/a/", "*.txt",SearchOption.AllDirectories).ToList(); LoadInterface("Interfaces/test_Listbox.goml"); // TestList [1].Field = "test string"; diff --git a/Tests/GOLIBTests.cs b/Tests/GOLIBTests.cs index 14c6c1a1..f5521f07 100644 --- a/Tests/GOLIBTests.cs +++ b/Tests/GOLIBTests.cs @@ -12,6 +12,7 @@ using System.Diagnostics; //using GGL; using go; using System.Threading; +using System.Collections.Generic; namespace test @@ -31,6 +32,7 @@ namespace test int frameCpt = 0; int idx = 0; string[] testFiles = { + "testCombobox.goml", "testBorder.goml", "testContainer.goml", "testLabel.goml", @@ -85,6 +87,13 @@ namespace test public string update = ""; #endregion + public List TestList = new List( new string[] + { + "string 1", + "string 2", + "string 3" + }); + protected override void OnLoad (EventArgs e) { base.OnLoad (e); diff --git a/Tests/Interfaces/testCombobox.goml b/Tests/Interfaces/testCombobox.goml new file mode 100755 index 00000000..c022d22c --- /dev/null +++ b/Tests/Interfaces/testCombobox.goml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 06eba842..ca65a6b0 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -165,6 +165,9 @@ PreserveNewest + + PreserveNewest + diff --git a/src/GraphicObjects/Combobox.cs b/src/GraphicObjects/Combobox.cs new file mode 100644 index 00000000..5cbc875e --- /dev/null +++ b/src/GraphicObjects/Combobox.cs @@ -0,0 +1,293 @@ +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; +using System.Collections; + +namespace go +{ + [DefaultTemplate("#go.Templates.Combobox.goml")] + [DefaultOverlayTemplate("#go.Templates.ComboboxOverlay.goml")] + public class Combobox : TemplatedContainer + { + #region CTOR + public Combobox() : base(){ } + #endregion + + bool _isPopped; + string text; + GraphicObject _overlay; + Group _list; + IList data; + int _selectedIndex; + object _selectedItem; + string _itemTemplate; + string _overlayTemplate; + + public event EventHandler SelectedItemChanged; + + #region implemented abstract members of TemplatedControl + protected override void loadTemplate (GraphicObject template) + { + base.loadTemplate (template); + loadOverlayTemplate (null); + } + public override GraphicObject Content { + get { + throw new NotImplementedException (); + } + set { + throw new NotImplementedException (); + } + } + #endregion + + protected virtual void loadOverlayTemplate(GraphicObject overlayTemplate) + { + if (overlayTemplate == null) { + DefaultOverlayTemplate dt = (DefaultOverlayTemplate)this.GetType ().GetCustomAttributes (typeof(DefaultOverlayTemplate), true).FirstOrDefault (); + Overlay = Interface.Load (dt.Path, this, !Interface.DontResoveGOML); + } else + Overlay = overlayTemplate; + _list = Overlay.FindByName ("List") as Group; + } + + [XmlAttributeAttribute][DefaultValue("#go.Templates.ItemTemplate.goml")] + public string ItemTemplate { + get { return _itemTemplate; } + set { + //TODO:reload list with new template? + _itemTemplate = value; + } + } + [XmlAttributeAttribute][DefaultValue("#go.Templates.ComboboxOverlay.goml")] + public string OverlayTemplate { + get { return _overlayTemplate; } + set { + //TODO:reload list with new template? + _overlayTemplate = value; + + Overlay = Interface.Load (_overlayTemplate, this, !Interface.DontResoveGOML); + _list = Overlay.FindByName ("List") as Group; + } + } + [XmlAttributeAttribute][DefaultValue(-1)] + public int SelectedIndex{ + get { return _selectedIndex; } + set { _selectedIndex = value; } + } + public object SelectedItem{ + set { + _selectedItem = value; + +// NotifyValueChanged ("SelectedItem", _selectedItem); +// + if (SelectedItem == null) + Text = ""; + else + Text = _selectedItem.ToString (); + } + + get { return _selectedItem; } + } + [XmlAttributeAttribute][DefaultValue(null)] + public IList Data { + get { + return data; + } + set { + data = value; + if (_list == null) + return; + + foreach (GraphicObject c in _list.Children) { + c.ClearBinding (); + } + _list.Children.Clear (); + _list.registerForGraphicUpdate (); + if (data == null) + return; + + #if DEBUG + Stopwatch loadingTime = new Stopwatch (); + loadingTime.Start (); + #endif + + MemoryStream ms = new MemoryStream (); + using (Stream stream = Interface.GetStreamFromPath (ItemTemplate)) + stream.CopyTo (ms); + + Type t = Interface.GetTopContainerOfGOMLStream (ms); + + foreach (var item in data) { + ms.Seek(0,SeekOrigin.Begin); + GraphicObject g = Interface.Load (ms, t, item); + g.MouseClick += itemClick; + _list.addChild(g); + } + + ms.Dispose (); + + #if DEBUG + loadingTime.Stop (); + Debug.WriteLine("Listbox Loading: {0} ticks \t, {1} ms", + loadingTime.ElapsedTicks, + loadingTime.ElapsedMilliseconds); + #endif + } + } + + void itemClick(object sender, OpenTK.Input.MouseButtonEventArgs e){ + object datasource = (sender as GraphicObject).DataSource; + SelectedItem = datasource; + SelectedItemChanged.Raise (sender, new SelectionChangeEventArgs(datasource)); + IsPopped = false; + + //Debug.WriteLine ((sender as GraphicObject).DataSource); + } + + public event EventHandler Pop; + public event EventHandler Unpop; + + public GraphicObject Overlay { + get { return _overlay; } + set { + if (_overlay != null) { + _overlay.LayoutChanged -= _overlay_LayoutChanged; + _overlay.MouseLeave -= _content_MouseLeave; + } + + _overlay = value; + + if (_overlay == null) + return; + + _overlay.Focusable = true; + _overlay.LayoutChanged += _overlay_LayoutChanged; + _overlay.MouseLeave += _content_MouseLeave; + } + } + + void _content_MouseLeave (object sender, MouseMoveEventArgs e) + { + IsPopped = false; + } + + void _overlay_LayoutChanged (object sender, LayoutChangeEventArgs e) + { + ILayoutable tc = Overlay.Parent as ILayoutable; + if (tc == null) + return; + Rectangle r = this.ScreenCoordinates (this.Slot); + if (e.LayoutType == LayoutingType.Width) { + if (Overlay.Slot.Width < tc.ClientRectangle.Width) { + if (r.Left + Overlay.Slot.Width > tc.ClientRectangle.Right) + Overlay.Left = tc.ClientRectangle.Right - Overlay.Slot.Width; + else + Overlay.Left = r.Left; + }else + Overlay.Left = 0; + }else if (e.LayoutType == LayoutingType.Height) { + if (Overlay.Slot.Height < tc.ClientRectangle.Height) { + if (r.Bottom + Overlay.Slot.Height > tc.ClientRectangle.Bottom) + Overlay.Top = r.Top - Overlay.Slot.Height; + else + Overlay.Top = r.Bottom; + }else + Overlay.Top = 0; + } + } + public override void ClearBinding () + { + //ensure popped window is cleared + if (Overlay != null) { + if (Overlay.Parent != null) { + IGOLibHost tc = Overlay.Parent as IGOLibHost; + if (tc != null) + tc.DeleteWidget (Overlay); + } + } + base.ClearBinding (); + + } + + [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to true + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + + [XmlAttributeAttribute()][DefaultValue("Combobox")] + public string Text { + get { return text; } + set { + if (text == value) + return; + text = value; + NotifyValueChanged ("Text", text); + } + } + + [XmlAttributeAttribute()][DefaultValue(false)] + public bool IsPopped + { + get { return _isPopped; } + set + { + _isPopped = value; + + if (_isPopped) { + onPop (this, null); + NotifyValueChanged ("SvgSub", "expanded"); + return; + } + + onUnpop (this, null); + NotifyValueChanged ("SvgSub", "collapsed"); + } + } + + public virtual void onPop(object sender, EventArgs e) + { + IGOLibHost tc = TopContainer; + if (tc == null) + return; + if (Overlay != null) { + Overlay.Visible = true; + if (Overlay.Parent == null) + tc.AddWidget (Overlay); + (tc as OpenTKGameWindow).PutOnTop (Overlay); + } + Pop.Raise (this, e); + } + public virtual void onUnpop(object sender, EventArgs e) + { + IGOLibHost tc = TopContainer; + if (tc == null) + return; + Overlay.Visible = false; + Unpop.Raise (this, e); + } + + public override void onMouseClick (object sender, MouseButtonEventArgs e) + { + IsPopped = !IsPopped; + base.onMouseClick (sender, e); + } + + } +} diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index a068a0d5..a78273ec 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -239,7 +239,7 @@ namespace go get { return _font; } set { _font = value; } } - [XmlAttributeAttribute()][DefaultValue(2.0)] + [XmlAttributeAttribute()][DefaultValue(0.0)] public virtual double CornerRadius { get { return _cornerRadius; } set { diff --git a/src/GraphicObjects/ListBox.cs b/src/GraphicObjects/ListBox.cs index a73791c8..4222bc50 100644 --- a/src/GraphicObjects/ListBox.cs +++ b/src/GraphicObjects/ListBox.cs @@ -25,19 +25,25 @@ using System.ComponentModel; //TODO: implement ItemTemplate node in xml using System.IO; using System.Diagnostics; +using System.Xml; namespace go { [DefaultTemplate("#go.Templates.Listbox.goml")] //[DefaultTemplate("#go.Templates.ItemTemplate.goml")] - public class ListBox : TemplatedControl + public class ListBox : TemplatedControl, IXmlSerializable { + #region CTOR + public ListBox () : base() {} + #endregion + Group _list; + IList data; + int _selectedIndex; + string _itemTemplate; - public ListBox () : base() - { - } + public event EventHandler SelectedItemChanged; #region implemented abstract members of TemplatedControl protected override void loadTemplate (GraphicObject template = null) @@ -47,21 +53,21 @@ namespace go } #endregion - IList data; - int _selectedIndex; - string _itemTemplate; - [XmlAttributeAttribute][DefaultValue("#go.Templates.ItemTemplate.goml")] public string ItemTemplate { get { return _itemTemplate; } - set { _itemTemplate = value; } + set { + //TODO:reload list with new template? + _itemTemplate = value; + } } + [XmlAttributeAttribute][DefaultValue(-1)] public int SelectedIndex{ get { return _selectedIndex; } set { _selectedIndex = value; } } public object SelectedItem{ - get { return data[_selectedIndex]; } + get { return data == null ? null : data[_selectedIndex]; } } [XmlAttributeAttribute][DefaultValue(null)] public IList Data { @@ -85,10 +91,8 @@ namespace go #endif MemoryStream ms = new MemoryStream (); - using (Stream stream = Interface.GetStreamFromPath (ItemTemplate)) { - + using (Stream stream = Interface.GetStreamFromPath (ItemTemplate)) stream.CopyTo (ms); - } Type t = Interface.GetTopContainerOfGOMLStream (ms); @@ -97,8 +101,8 @@ namespace go GraphicObject g = Interface.Load (ms, t, item); g.MouseClick += itemClick; _list.addChild(g); - } + ms.Dispose (); #if DEBUG @@ -109,10 +113,72 @@ namespace go #endif } } + void itemClick(object sender, OpenTK.Input.MouseButtonEventArgs e){ + SelectedItemChanged.Raise (sender, new SelectionChangeEventArgs((sender as GraphicObject).DataSource)); NotifyValueChanged ("SelectedItem", (sender as GraphicObject).DataSource); //Debug.WriteLine ((sender as GraphicObject).DataSource); } + + #region IXmlSerializable + public override System.Xml.Schema.XmlSchema GetSchema(){ return null; } + public override void ReadXml(System.Xml.XmlReader reader) + { + //Template could be either an attribute containing path or expressed inlined + //as a Template Element + using (System.Xml.XmlReader subTree = reader.ReadSubtree()) + { + subTree.Read (); + + string template = reader.GetAttribute ("Template"); + string tmp = subTree.ReadOuterXml (); + + //Load template from path set as attribute in templated control + if (string.IsNullOrEmpty (template)) { + //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 + break; + } else { + xr.ReadInnerXml (); + } + } + } + } else + loadTemplate (Interface.Load (template, this, !Interface.DontResoveGOML)); + + + //normal xml read + using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { + xr.Read (); + base.ReadXml(xr); + } + } + } + public override void WriteXml(System.Xml.XmlWriter writer) + { + //TODO: + throw new NotImplementedException(); + } + #endregion } } diff --git a/src/GraphicObjects/TemplatedControl.cs b/src/GraphicObjects/TemplatedControl.cs index 0599c6e3..4dbe21e5 100644 --- a/src/GraphicObjects/TemplatedControl.cs +++ b/src/GraphicObjects/TemplatedControl.cs @@ -28,37 +28,44 @@ using System.Diagnostics; namespace go { - [AttributeUsage(AttributeTargets.Class)] - public class DefaultTemplate : Attribute +// [AttributeUsage(AttributeTargets.Class)] + public class TemplateAttribute : Attribute { public string Path = ""; - public DefaultTemplate(string path) + public TemplateAttribute(string path) { Path = path; } } [AttributeUsage(AttributeTargets.Class)] - public class DefaultItemTemplate : Attribute + public class DefaultTemplate : TemplateAttribute { - public string Path = ""; - public DefaultItemTemplate(string path) - { - Path = path; - } + public DefaultTemplate(string path) : base(path){} + } + [AttributeUsage(AttributeTargets.Class)] + public class DefaultOverlayTemplate : TemplateAttribute + { + public DefaultOverlayTemplate(string path) : base(path){} + } + [AttributeUsage(AttributeTargets.Class)] + public class DefaultItemTemplate : TemplateAttribute + { + public DefaultItemTemplate(string path) : base(path){} } public abstract class TemplatedControl : PrivateContainer, IXmlSerializable { - public TemplatedControl () : base() - { - } + #region CTOR + public TemplatedControl () : base() {} + #endregion + + string _template; -// string _templatePath; -// [XmlAttributeAttribute()] -// public virtual string Template { -// get { return _templatePath; } -// set { _templatePath = value; } -// } + [XmlAttributeAttribute][DefaultValue("#go.Templates.Template.goml")] + public string Template { + get { return _template; } + set { _template = value; } + } #region GraphicObject overrides [XmlAttributeAttribute()][DefaultValue(-1)] @@ -110,7 +117,6 @@ namespace go } #region IXmlSerializable - public override System.Xml.Schema.XmlSchema GetSchema(){ return null; } public override void ReadXml(System.Xml.XmlReader reader) { @@ -165,16 +171,9 @@ namespace go } public override void WriteXml(System.Xml.XmlWriter writer) { - base.WriteXml(writer); -// -// if (child == null) -// return; -// -// writer.WriteStartElement(child.GetType().Name); -// (child as IXmlSerializable).WriteXml(writer); -// writer.WriteEndElement(); + //TODO: + throw new NotImplementedException(); } - #endregion } } diff --git a/src/Interface.cs b/src/Interface.cs index 723bdad7..551cd1d3 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -61,7 +61,7 @@ namespace go if (dstIdx < 0) { if (FreeRefIndices.Count == 0) { - dstIdx = Interface.References.Count; + dstIdx = Interface.References.Count(); Interface.References.Add (o); } else { dstIdx = FreeRefIndices.Dequeue (); diff --git a/src/SelectionChangeEventArgs.cs b/src/SelectionChangeEventArgs.cs new file mode 100644 index 00000000..da706db7 --- /dev/null +++ b/src/SelectionChangeEventArgs.cs @@ -0,0 +1,16 @@ +using System; + +namespace go +{ + public class SelectionChangeEventArgs: EventArgs + { + public object NewValue; + + + public SelectionChangeEventArgs (object _newValue) : base() + { + NewValue = _newValue; + } + } +} + -- 2.47.3