diff options
| author | jpbruyere <jp.bruyere@hotmail.com> | 2016-02-17 08:44:34 +0100 |
|---|---|---|
| committer | jpbruyere <jp.bruyere@hotmail.com> | 2016-02-17 08:44:34 +0100 |
| commit | a8156b149f2e4a3c087bcb090db293d08116bd67 (patch) | |
| tree | 51dd4165422863f70c656de8e0bbfa7c079142bb /src/GraphicObjects | |
| parent | 3c1dbdbbc58d38d45276e3147c3717d19a69adf2 (diff) | |
| parent | bf27b88a6cbfcc65d7ed6360f9193d52f96b1598 (diff) | |
Merge branch 'DefTemplateSizing0'
Diffstat (limited to 'src/GraphicObjects')
24 files changed, 1120 insertions, 471 deletions
diff --git a/src/GraphicObjects/Border.cs b/src/GraphicObjects/Border.cs index 7011690e..be08a7d8 100644 --- a/src/GraphicObjects/Border.cs +++ b/src/GraphicObjects/Border.cs @@ -40,9 +40,10 @@ namespace Crow } } - protected override Size measureRawSize () + protected override int measureRawSize (LayoutingType lt) { - return child == null ? Bounds.Size : child.Slot.Size + 2 * (Margin + BorderWidth); + int tmp = base.measureRawSize (lt); + return tmp < 0 ? tmp : tmp + 2 * BorderWidth; } protected override void onDraw (Cairo.Context gr) { diff --git a/src/GraphicObjects/Button.cs b/src/GraphicObjects/Button.cs index 5bf11f68..9903888b 100644 --- a/src/GraphicObjects/Button.cs +++ b/src/GraphicObjects/Button.cs @@ -18,12 +18,7 @@ namespace Crow { #region CTOR public Button() : base() - { - //MouseEnter += delegate { Background = Color.RedDevil;}; - //MouseLeave += delegate { Background = Color.Transparent;}; -// MouseButtonDown += delegate { BackImgSub = "pressed"; registerForGraphicUpdate();}; -// MouseButtonUp += delegate { BackImgSub = "normal";registerForGraphicUpdate();}; - } + {} #endregion string caption; diff --git a/src/GraphicObjects/CheckBox.cs b/src/GraphicObjects/CheckBox.cs index fa34522d..05bb0cac 100644 --- a/src/GraphicObjects/CheckBox.cs +++ b/src/GraphicObjects/CheckBox.cs @@ -1,24 +1,13 @@ 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.Serialization; namespace Crow { [DefaultTemplate("#Crow.Templates.CheckBox.goml")] - public class CheckBox : TemplatedControl - { + public class CheckBox : TemplatedControl + { string caption; string image; bool isChecked; @@ -33,12 +22,7 @@ namespace Crow public event EventHandler Unchecked; #region GraphicObject overrides -// [XmlAttributeAttribute()][DefaultValue(-1)] -// public override int Height { -// get { return base.Height; } -// set { base.Height = value; } -// } - [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to true + [XmlAttributeAttribute()][DefaultValue(true)] public override bool Focusable { get { return base.Focusable; } diff --git a/src/GraphicObjects/DummyTemplate.cs b/src/GraphicObjects/DummyTemplate.cs new file mode 100644 index 00000000..68597d18 --- /dev/null +++ b/src/GraphicObjects/DummyTemplate.cs @@ -0,0 +1,33 @@ +// +// DummyTemplate.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; + +namespace Crow +{ + [DefaultTemplate("#Crow.Templates.Dummy.goml")] + public class DummyTemplate : TemplatedControl + { + public DummyTemplate () : base() + { + } + } +} + diff --git a/src/GraphicObjects/Expandable.cs b/src/GraphicObjects/Expandable.cs index f44e5e27..4214ed93 100644 --- a/src/GraphicObjects/Expandable.cs +++ b/src/GraphicObjects/Expandable.cs @@ -1,33 +1,39 @@ 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.Xml.Serialization; namespace Crow { [DefaultTemplate("#Crow.Templates.Expandable.goml")] public class Expandable : TemplatedContainer - { + { + #region CTOR + public Expandable() : base() + { + } + #endregion + + #region Private fields bool _isExpanded; string caption; string image; Container _contentContainer; + #endregion + #region Event Handlers public event EventHandler Expand; public event EventHandler Collapse; + #endregion + + #region GraphicObject overrides + [XmlAttributeAttribute()][DefaultValue(true)] + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + #endregion public override GraphicObject Content { get { @@ -37,30 +43,25 @@ namespace Crow _contentContainer.SetChild(value); } } - - public Expandable() : base() - { - } - protected override void loadTemplate(GraphicObject template = null) { base.loadTemplate (template); _contentContainer = this.child.FindByName ("Content") as Container; } - - [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to true - public override bool Focusable + public override void onMouseClick (object sender, MouseButtonEventArgs e) { - get { return base.Focusable; } - set { base.Focusable = value; } + IsExpanded = !IsExpanded; + base.onMouseClick (sender, e); } - [XmlAttributeAttribute()][DefaultValue(-1)] - public override int Height { - get { return base.Height; } - set { base.Height = value; } + public override void ResolveBindings () + { + base.ResolveBindings (); + if (Content != null) + Content.ResolveBindings (); } + #region Public properties [XmlAttributeAttribute()][DefaultValue("Expandable")] public string Caption { get { return caption; } @@ -99,6 +100,7 @@ namespace Crow NotifyValueChanged ("SvgSub", "collapsed"); } } + #endregion public virtual void onExpand(object sender, EventArgs e) { @@ -114,17 +116,5 @@ namespace Crow Collapse.Raise (this, e); } - - public override void onMouseClick (object sender, MouseButtonEventArgs e) - { - IsExpanded = !IsExpanded; - base.onMouseClick (sender, e); - } - public override void ResolveBindings () - { - base.ResolveBindings (); - if (Content != null) - Content.ResolveBindings (); - } } } diff --git a/src/GraphicObjects/GenericStack.cs b/src/GraphicObjects/GenericStack.cs index 665ba65d..2a1da6c3 100644 --- a/src/GraphicObjects/GenericStack.cs +++ b/src/GraphicObjects/GenericStack.cs @@ -10,12 +10,6 @@ namespace Crow { public class GenericStack : Group { - internal class Page - { - public byte[] bmp; - public int Size; - } - #region CTOR public GenericStack() : base() @@ -28,18 +22,6 @@ namespace Crow Orientation _orientation; #endregion - public override T AddChild<T> (T child) - { - T tmp = base.AddChild (child); - this.RegisterForLayouting (LayoutingType.PositionChildren); - return tmp; - } - public override void RemoveChild (GraphicObject child) - { - base.RemoveChild (child); - this.RegisterForLayouting (LayoutingType.PositionChildren); - } - #region Public Properties [XmlAttributeAttribute()][DefaultValue(2)] public int Spacing @@ -61,40 +43,55 @@ namespace Crow #endregion #region GraphicObject Overrides - protected override Size measureRawSize () + public override bool ArrangeChildren { get { return true; } } + public override void ChildrenLayoutingConstraints (ref LayoutingType layoutType) { - Size tmp = new Size (); - - if (Orientation == Orientation.Horizontal) { - foreach (GraphicObject c in Children) { - if (!c.Visible) - continue; - tmp.Width += c.Slot.Width + Spacing; - tmp.Height = Math.Max (tmp.Height, Math.Max(c.Slot.Bottom, c.Slot.Height)); - } - if (tmp.Width > 0) - tmp.Width -= Spacing; - } else { - foreach (GraphicObject c in Children) { - if (!c.Visible) - continue; - tmp.Width = Math.Max (tmp.Width, Math.Max(c.Slot.Right, c.Slot.Width)); - tmp.Height += c.Slot.Height + Spacing; + //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 tmp = 0; + switch (lt) { + case LayoutingType.Width: + if (Orientation == Orientation.Horizontal) { + if (Children.Count > 0) { + foreach (GraphicObject c in Children) { + if (!c.Visible) + continue; + if (c.RegisteredLayoutings.HasFlag (LayoutingType.Width)) + return -1; + tmp += c.Slot.Width + Spacing; + } + tmp -= Spacing; + } + break; + } + return base.measureRawSize (lt); + case LayoutingType.Height: + if (Orientation == Orientation.Vertical) { + if (Children.Count > 0) { + foreach (GraphicObject c in Children) { + if (!c.Visible) + continue; + if (c.RegisteredLayoutings.HasFlag (LayoutingType.Height)) + return -1; + tmp += c.Slot.Height + Spacing; + } + tmp -= Spacing; + } + break; } - if (tmp.Height > 0) - tmp.Height -= Spacing; + return base.measureRawSize (lt); } - tmp.Width += 2 * Margin; - tmp.Height += 2 * Margin; - - return tmp; + return tmp + 2 * Margin; } public virtual void ComputeChildrenPositions() { - #if DEBUG_LAYOUTING - Debug.WriteLine("ComputeChildrenPosition: " + this.ToString()); - #endif int d = 0; if (Orientation == Orientation.Horizontal) { foreach (GraphicObject c in Children) { @@ -120,86 +117,87 @@ namespace Crow { RegisteredLayoutings &= (~layoutType); - LayoutingType childSizeToCheck; - if (Orientation == Orientation.Horizontal) - childSizeToCheck = LayoutingType.Width; - else - childSizeToCheck = LayoutingType.Height; - - foreach (GraphicObject g in Children) { - if (!g.Visible) - continue; - if (g.RegisteredLayoutings.HasFlag (childSizeToCheck)) - return false; - } - - if (layoutType == LayoutingType.PositionChildren) { - //allow 1 child to have size to 0 if stack has fixed or streched size, + 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. if (Orientation == Orientation.Horizontal) { - if (Width >= 0) { - GraphicObject stretchedGO = null; - int tmpWidth = Slot.Width; - int cptChildren = 0; - for (int i = 0; i < Children.Count; i++) { - if (!Children [i].Visible) - continue; - cptChildren++; - if (Children [i].Width == 0) { - if (stretchedGO != null) - throw new Exception ("Only one child in stack may have size to stretched"); - stretchedGO = Children [i]; - if (i < Children.Count - 1) - tmpWidth -= Spacing; - continue; + GraphicObject stretchedGO = null; + int tmpWidth = Slot.Width; + int cptChildren = 0; + for (int i = 0; i < Children.Count; i++) { + if (!Children [i].Visible) + continue; + //requeue Positionning if child is not layouted + if (Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Width)) + return false; + cptChildren++; + if (Children [i].Width == 0) { + if (!(stretchedGO == null && Width >= 0)) { + //change size policy of other stretched children + Children [i].Width = -1; + return false; } - tmpWidth -= Children[i].Slot.Width + Spacing; + stretchedGO = Children [i]; + if (i < Children.Count - 1) + tmpWidth -= Spacing; + continue; } - if (stretchedGO != null) { - tmpWidth += (Spacing - 2 * Margin); - if (tmpWidth < MinimumSize.Width) - tmpWidth = MinimumSize.Width; - else if (tmpWidth > MaximumSize.Width && MaximumSize.Width > 0) - tmpWidth = MaximumSize.Width; - if (stretchedGO.LastSlots.Width != tmpWidth) { - stretchedGO.Slot.Width = tmpWidth; - stretchedGO.bmp = null; - stretchedGO.OnLayoutChanges (LayoutingType.Width); - stretchedGO.LastSlots.Width = stretchedGO.Slot.Width; - } + tmpWidth -= Children [i].Slot.Width + Spacing; + } + if (stretchedGO != null && Width >= 0) { + tmpWidth += (Spacing - 2 * Margin); + if (tmpWidth < MinimumSize.Width) + tmpWidth = MinimumSize.Width; + else if (tmpWidth > MaximumSize.Width && MaximumSize.Width > 0) + tmpWidth = MaximumSize.Width; + if (stretchedGO.LastSlots.Width != tmpWidth) { + stretchedGO.Slot.Width = tmpWidth; + stretchedGO.bmp = null; + #if DEBUG_LAYOUTING + Debug.WriteLine ("\tAdjusting Width of " + stretchedGO.ToString()); + #endif + stretchedGO.OnLayoutChanges (LayoutingType.Width); + stretchedGO.LastSlots.Width = stretchedGO.Slot.Width; } - } + } } else { - if (Height >= 0) { - GraphicObject stretchedGO = null; - int tmpHeight = Slot.Height; - int cptChildren = 0; - for (int i = 0; i < Children.Count; i++) { - if (!Children [i].Visible) - continue; - cptChildren++; - if (Children [i].Height == 0) { - if (stretchedGO != null) - throw new Exception ("Only one child in stack may have size to stretched"); - stretchedGO = Children [i]; - if (i < Children.Count - 1) - tmpHeight -= Spacing; - continue; + GraphicObject stretchedGO = null; + int tmpHeight = Slot.Height; + int cptChildren = 0; + for (int i = 0; i < Children.Count; i++) { + if (!Children [i].Visible) + continue; + if (Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Height)) + return false; + cptChildren++; + if (Children [i].Height == 0) { + if (!(stretchedGO == null && Height >= 0)){ + Children [i].Height = -1; + return false; } - tmpHeight -= Children[i].Slot.Height + Spacing; + stretchedGO = Children [i]; + if (i < Children.Count - 1) + tmpHeight -= Spacing; + continue; } - if (stretchedGO != null) { - tmpHeight += (Spacing - 2 * Margin); - if (tmpHeight < MinimumSize.Height) - tmpHeight = MinimumSize.Height; - else if (tmpHeight > MaximumSize.Height && MaximumSize.Height > 0) - tmpHeight = MaximumSize.Height; - if (stretchedGO.LastSlots.Height != tmpHeight) { - stretchedGO.Slot.Height = tmpHeight; - stretchedGO.bmp = null; - stretchedGO.OnLayoutChanges (LayoutingType.Height); - stretchedGO.LastSlots.Height = stretchedGO.Slot.Height; - } + tmpHeight -= Children[i].Slot.Height + Spacing; + } + if (stretchedGO != null && Height >= 0) { + tmpHeight += (Spacing - 2 * Margin); + if (tmpHeight < MinimumSize.Height) + tmpHeight = MinimumSize.Height; + else if (tmpHeight > MaximumSize.Height && MaximumSize.Height > 0) + tmpHeight = MaximumSize.Height; + if (stretchedGO.LastSlots.Height != tmpHeight) { + stretchedGO.Slot.Height = tmpHeight; + stretchedGO.bmp = null; + #if DEBUG_LAYOUTING + Debug.WriteLine ("\tAdjusting Height of " + stretchedGO.ToString()); + #endif + stretchedGO.OnLayoutChanges (LayoutingType.Height); + stretchedGO.LastSlots.Height = stretchedGO.Slot.Height; } } } @@ -226,14 +224,14 @@ namespace Crow if (Orientation == Orientation.Horizontal) { if (this.Bounds.Width < 0) this.RegisterForLayouting (LayoutingType.Width); - this.RegisterForLayouting (LayoutingType.PositionChildren); + this.RegisterForLayouting (LayoutingType.ArrangeChildren); } break; case LayoutingType.Height: if (Orientation == Orientation.Vertical) { if (this.Bounds.Height < 0) this.RegisterForLayouting (LayoutingType.Height); - this.RegisterForLayouting (LayoutingType.PositionChildren); + this.RegisterForLayouting (LayoutingType.ArrangeChildren); } break; } diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index 171a8eaa..9f20fca9 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -1,23 +1,14 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; - -//using OpenTK.Graphics.OpenGL; -using System.Drawing.Imaging; +using System.ComponentModel; using System.Diagnostics; -using OpenTK.Input; - -using Cairo; - -using System.Xml.Serialization; +using System.Linq; using System.Reflection; -using System.ComponentModel; -using System.IO; -//using System.Xml; -using System.Xml; -using System.Runtime.CompilerServices; using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using System.Xml.Serialization; +using Cairo; +using OpenTK.Input; namespace Crow { @@ -54,7 +45,6 @@ namespace Crow return; loadDefaultValues (); - registerForGraphicUpdate (); } public GraphicObject (Rectangle _bounds) { @@ -63,7 +53,6 @@ namespace Crow loadDefaultValues (); Bounds = _bounds; - registerForGraphicUpdate (); } #endregion @@ -249,6 +238,8 @@ namespace Crow Bounds.Width = value; NotifyValueChanged ("Width", Bounds.Width); + NotifyValueChanged ("WidthPolicy", WidthPolicy); + this.RegisterForLayouting (LayoutingType.Width); } } @@ -261,17 +252,22 @@ namespace Crow Bounds.Height = value; NotifyValueChanged ("Height", Bounds.Height); + NotifyValueChanged ("HeightPolicy", HeightPolicy); + this.RegisterForLayouting (LayoutingType.Height); } } + [XmlIgnore]public virtual int WidthPolicy { get { return Width < 1 ? Width : 0; } } + [XmlIgnore]public virtual int HeightPolicy { get { return Height < 1 ? Height : 0; } } + [XmlAttributeAttribute()][DefaultValue(false)] public virtual bool Fit { - get { return Bounds.Width < 0 && Bounds.Height < 0 ? true : false; } + get { return Width < 0 && Height < 0 ? true : false; } set { if (value == Fit) return; - Bounds.Width = Bounds.Height = -1; + Width = Height = -1; } } [XmlAttributeAttribute()][DefaultValue(false)] @@ -385,12 +381,14 @@ namespace Crow if (!_isVisible && this.Contains (HostContainer.hoverWidget)) HostContainer.hoverWidget = null; + if (Parent is GraphicObject) + Parent.RegisterForLayouting (LayoutingType.Sizing); if (Parent is GenericStack) - Parent.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.PositionChildren); - + Parent.RegisterForLayouting (LayoutingType.ArrangeChildren); RegisterForLayouting (LayoutingType.Sizing); RegisterForRedraw (); + NotifyValueChanged ("Visible", _isVisible); } } @@ -426,7 +424,7 @@ namespace Crow /// <summary> Loads the default values from XML attributes default </summary> protected virtual void loadDefaultValues() - { + { Type thisType = this.GetType (); if (Interface.DefaultValuesLoader.ContainsKey(thisType.FullName)) { Interface.DefaultValuesLoader[thisType.FullName] (this); @@ -451,20 +449,19 @@ namespace Crow il.Emit(OpCodes.Nop); + StyleAttribute[] style = thisType.GetCustomAttributes().OfType<StyleAttribute>().ToArray(); + foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { string name = ""; + object defaultValue = null; #region retrieve custom attributes if (pi.GetSetMethod () == null) continue; + XmlIgnoreAttribute xia = (XmlIgnoreAttribute)pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)); if (xia != null) - continue; - DefaultValueAttribute dv = (DefaultValueAttribute)pi.GetCustomAttribute (typeof(DefaultValueAttribute)); - if (dv == null) - continue; - object defaultValue = dv.Value; - + continue; XmlAttributeAttribute xaa = (XmlAttributeAttribute)pi.GetCustomAttribute (typeof(XmlAttributeAttribute)); if (xaa != null) { if (string.IsNullOrEmpty (xaa.AttributeName)) @@ -472,6 +469,16 @@ namespace Crow else name = xaa.AttributeName; } + + StyleAttribute piStyle = style.Where(s => s.PropertyName == pi.Name).FirstOrDefault(); + if (piStyle != null){ + defaultValue = piStyle.DefaultValue; + }else{ + DefaultValueAttribute dv = (DefaultValueAttribute)pi.GetCustomAttribute (typeof(DefaultValueAttribute)); + if (dv == null) + continue; + defaultValue = dv.Value; + } #endregion il.Emit (OpCodes.Ldarg_0); @@ -618,12 +625,15 @@ namespace Crow get { return layoutingTries; } set { layoutingTries = value; } } - /// <summary> return size of content + margins </summary> - protected virtual Size measureRawSize () { - return Bounds.Size; + protected virtual int measureRawSize (LayoutingType lt) { + return lt == LayoutingType.Width ? Bounds.Size.Width : Bounds.Size.Height; } + /// <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; @@ -633,15 +643,12 @@ namespace Crow if (Height == 0) layoutType &= (~LayoutingType.Y); - //Prevent child repositionning in a stack - //TODO:this should be done inside GenericStack - GenericStack gs = Parent as GenericStack; - if (gs != null) { - if (gs.Orientation == Orientation.Horizontal) - layoutType &= (~LayoutingType.X); - else - layoutType &= (~LayoutingType.Y); - } + if (!ArrangeChildren) + layoutType &= (~LayoutingType.ArrangeChildren); + + //apply constraints depending on parent type + if (Parent is GraphicObject) + (Parent as GraphicObject).ChildrenLayoutingConstraints (ref layoutType); //prevent queueing same LayoutingType for this layoutType &= (~RegisteredLayoutings); @@ -650,7 +657,7 @@ namespace Crow return; #if DEBUG_LAYOUTING - Debug.WriteLine ("RegisterForLayouting => {1}->{0}", layoutType, this.ToString()); + Debug.WriteLine ("REGLayout => {1}->{0}", layoutType, this.ToString()); #endif //enqueue LQI LayoutingTypes separately @@ -662,15 +669,15 @@ namespace Crow Interface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.X, this)); if (layoutType.HasFlag (LayoutingType.Y)) Interface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Y, this)); - if (layoutType.HasFlag (LayoutingType.PositionChildren)) - Interface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.PositionChildren, this)); + if (layoutType.HasFlag (LayoutingType.ArrangeChildren)) + Interface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this)); } /// <summary> trigger dependant sizing component update </summary> public virtual void OnLayoutChanges(LayoutingType layoutType) { #if DEBUG_LAYOUTING - Debug.WriteLine ("Layout change: " + this.ToString () + ":" + LastSlots.ToString() + "=>" + Slot.ToString ()); + Debug.WriteLine ("\t " + LastSlots.ToString() + "\n\t => " + Slot.ToString ()); #endif switch (layoutType) { @@ -697,7 +704,8 @@ namespace Crow case LayoutingType.X: if (Bounds.X == 0) { - if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width)) + if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width) || + RegisteredLayoutings.HasFlag (LayoutingType.Width)) return false; switch (HorizontalAlignment) { @@ -726,7 +734,8 @@ namespace Crow case LayoutingType.Y: if (Bounds.Y == 0) { - if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height)) + if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height) || + RegisteredLayoutings.HasFlag (LayoutingType.Height)) return false; switch (VerticalAlignment) { @@ -753,16 +762,14 @@ namespace Crow LastSlots.Y = Slot.Y; break; case LayoutingType.Width: - //force sizing to fit if parent is sizing on children and - //this object has stretched size - if (Parent.getBounds ().Width < 0 && Width == 0) - Width = -1; - if (Width > 0) Slot.Width = Width; - else if (Width < 0) - Slot.Width = measureRawSize ().Width; - else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width)) + else if (Width < 0) { + int tmp = measureRawSize (LayoutingType.Width); + if (tmp < 0) + return false; + Slot.Width = tmp; + }else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width)) return false; else Slot.Width = Parent.ClientRectangle.Width; @@ -783,15 +790,14 @@ namespace Crow LastSlots.Width = Slot.Width; break; case LayoutingType.Height: - //force sizing to fit if parent is sizing on children - if (Parent.getBounds ().Height < 0 && Height == 0) - Height = -1; - if (Height > 0) Slot.Height = Height; - else if (Height < 0) - Slot.Height = measureRawSize ().Height; - else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height)) + else if (Height < 0){ + int tmp = measureRawSize (LayoutingType.Height); + if (tmp < 0) + return false; + Slot.Height = tmp; + }else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height)) return false; else Slot.Height = Parent.ClientRectangle.Height; @@ -915,8 +921,11 @@ namespace Crow return false; if (ScreenCoordinates (Slot).ContainsOrIsEqual (m)) { Scroller scr = Parent as Scroller; - if (scr == null) - return true; + if (scr == null) { + if (Parent is GraphicObject) + return (Parent as GraphicObject).MouseIsIn (m); + else return true; + } return scr.MouseIsIn (scr.savedMousePos); } return false; @@ -1013,11 +1022,11 @@ namespace Crow #region Binding public virtual void ResolveBindings() { + if (Bindings.Count == 0) + return; #if DEBUG_BINDING Debug.WriteLine ("ResolveBinding => " + this.ToString ()); #endif - if (Bindings.Count == 0) - return; Dictionary<object,List<Binding>> resolved = new Dictionary<object, List<Binding>>(); foreach (Binding b in Bindings) { if (b.Resolved) @@ -1028,12 +1037,14 @@ namespace Crow continue; } } - if (!b.FindTarget ()) + if (!b.FindTarget ()) { + Debug.WriteLine ("BINDING ERROR: target not found => " + b.ToString()); continue; + } if (b.Source.Member.MemberType == MemberTypes.Event) { //register handler for event if (b.Target.Method == null) { - Debug.WriteLine ("Handler Method not found: " + b.Expression); + Debug.WriteLine ("Handler Method not found: " + b.ToString()); continue; } @@ -1041,6 +1052,9 @@ namespace Crow Delegate del = Delegate.CreateDelegate (b.Source.Event.EventHandlerType, b.Target.Instance, b.Target.Method); addHandler.Invoke (this, new object[] { del }); b.Resolved = true; + #if DEBUG_BINDING + Debug.WriteLine ("\tHandler binded => " + b.ToString()); + #endif continue; } List<Binding> bindings = null; @@ -1050,6 +1064,9 @@ namespace Crow } bindings.Add (b); b.Resolved = true; + #if DEBUG_BINDING + Debug.WriteLine ("\tmarked as resolved => " + b.ToString()); + #endif } MethodInfo stringEquals = typeof(string).GetMethod @@ -1336,6 +1353,9 @@ namespace Crow addHandler.Invoke(this, new object[] {del}); binding.Resolved = true; + #if DEBUG_BINDING + Debug.WriteLine ("\tCompiled Event Source => " + binding.ToString()); + #endif } /// <summary> /// Remove dynamic delegates by ids from dataSource diff --git a/src/GraphicObjects/Grid.cs b/src/GraphicObjects/Grid.cs index c242899f..281f4ae0 100644 --- a/src/GraphicObjects/Grid.cs +++ b/src/GraphicObjects/Grid.cs @@ -32,13 +32,13 @@ namespace Crow public override T AddChild<T> (T child) { T tmp = base.AddChild (child); - this.RegisterForLayouting (LayoutingType.PositionChildren); + this.RegisterForLayouting (LayoutingType.ArrangeChildren); return tmp; } public override void RemoveChild (GraphicObject child) { base.RemoveChild (child); - this.RegisterForLayouting (LayoutingType.PositionChildren); + this.RegisterForLayouting (LayoutingType.ArrangeChildren); } #region Public Properties @@ -59,7 +59,7 @@ namespace Crow _columnCount = value; NotifyValueChanged ("ColumnCount", ColumnCount); - this.RegisterForLayouting (LayoutingType.PositionChildren); + this.RegisterForLayouting (LayoutingType.ArrangeChildren); } } [XmlAttributeAttribute()][DefaultValue(1)] @@ -73,7 +73,7 @@ namespace Crow _rowCount = value; NotifyValueChanged ("RowCount", RowCount); - this.RegisterForLayouting (LayoutingType.PositionChildren); + this.RegisterForLayouting (LayoutingType.ArrangeChildren); } } public virtual int CaseWidth { @@ -130,7 +130,7 @@ namespace Crow { RegisteredLayoutings &= (~layoutType); - if (layoutType == LayoutingType.PositionChildren) { + if (layoutType == LayoutingType.ArrangeChildren) { ComputeChildrenPositions (); diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index 486e07f9..6e2417a9 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Drawing; -using System.Diagnostics; -using Cairo; -using System.Xml.Serialization; using System.ComponentModel; +using System.Xml.Serialization; +using Cairo; +using OpenTK.Input; + namespace Crow { @@ -45,9 +43,9 @@ namespace Crow public virtual T AddChild<T>(T child) { GraphicObject g = child as GraphicObject; - children.Add(g); + Children.Add(g); g.Parent = this as GraphicObject; - g.RegisterForLayouting (LayoutingType.Sizing); + g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); g.LayoutChanged += OnChildLayoutChanges; return (T)child; } @@ -55,36 +53,46 @@ namespace Crow { child.LayoutChanged -= OnChildLayoutChanges; child.ClearBinding (); - child.Parent = null; - children.Remove(child); - this.RegisterForLayouting (LayoutingType.Sizing); + //child.Parent = null; + Children.Remove(child); + + if (child == largestChild) + searchLargestChild (); + if (child == tallestChild) + searchTallestChild (); + + this.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); } public virtual void ClearChildren() { - while(children.Count > 0){ - GraphicObject g = children[children.Count-1]; + while(Children.Count > 0){ + GraphicObject g = Children[Children.Count-1]; g.LayoutChanged -= OnChildLayoutChanges; g.ClearBinding (); g.Parent = null; - children.RemoveAt(children.Count-1); + Children.RemoveAt(Children.Count-1); } + + resetChildrenMaxSize (); + this.RegisterForLayouting (LayoutingType.Sizing); ChildrenCleared.Raise (this, new EventArgs ()); } + public void putWidgetOnTop(GraphicObject w) { - if (children.Contains(w)) + if (Children.Contains(w)) { - children.Remove(w); - children.Add(w); + Children.Remove(w); + Children.Add(w); } } public void putWidgetOnBottom(GraphicObject w) { - if (children.Contains(w)) + if (Children.Contains(w)) { - children.Remove(w); - children.Insert(0, w); + Children.Remove(w); + Children.Insert(0, w); } } @@ -92,7 +100,7 @@ namespace Crow public override void ResolveBindings () { base.ResolveBindings (); - foreach (GraphicObject w in children) + foreach (GraphicObject w in Children) w.ResolveBindings (); } public override GraphicObject FindByName (string nameToFind) @@ -100,7 +108,7 @@ namespace Crow if (Name == nameToFind) return this; - foreach (GraphicObject w in children) { + foreach (GraphicObject w in Children) { GraphicObject r = w.FindByName (nameToFind); if (r != null) return r; @@ -109,7 +117,7 @@ namespace Crow } public override bool Contains (GraphicObject goToFind) { - foreach (GraphicObject w in children) { + foreach (GraphicObject w in Children) { if (w == goToFind) return true; if (w.Contains (goToFind)) @@ -117,9 +125,30 @@ namespace Crow } return false; } - protected override Size measureRawSize () + protected override int measureRawSize (LayoutingType lt) { - return new Size(maxChildrenWidth + 2 * Margin, maxChildrenHeight + 2 * Margin); + if (Children.Count == 0) + return base.measureRawSize (lt); + + 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 = -1; + return -1;//cancel actual sizing to let child computation take place + } + return maxChildrenWidth + 2 * Margin; + }else{ + if (tallestChild == null) + searchTallestChild (); + if (tallestChild == null) { + Children[0].Height = -1; + return -1; + } + return maxChildrenHeight + 2 * Margin; + } } public override void OnLayoutChanges (LayoutingType layoutType) @@ -129,14 +158,14 @@ namespace Crow //position smaller objects in group when group size is fit switch (layoutType) { case LayoutingType.Width: - foreach (GraphicObject c in children) { + foreach (GraphicObject c in Children) { if (!c.Visible) continue; c.RegisterForLayouting (LayoutingType.X | LayoutingType.Width); } break; case LayoutingType.Height: - foreach (GraphicObject c in children) { + foreach (GraphicObject c in Children) { if (!c.Visible) continue; c.RegisterForLayouting (LayoutingType.Y | LayoutingType.Height); } @@ -147,10 +176,6 @@ namespace Crow { GraphicObject g = sender as GraphicObject; switch (arg.LayoutType) { - case LayoutingType.X: - break; - case LayoutingType.Y: - break; case LayoutingType.Width: if (g.Slot.Width > maxChildrenWidth) { maxChildrenWidth = g.Slot.Width; @@ -158,15 +183,10 @@ namespace Crow if (this.Bounds.Width < 0) this.RegisterForLayouting (LayoutingType.Width); } else if (g == largestChild) { - //search for the new largest child + largestChild = null; maxChildrenWidth = 0; - for (int i = 0; i < children.Count; i++) { - if (children [i].Slot.Width > maxChildrenWidth) { - maxChildrenWidth = children [i].Slot.Width; - largestChild = children [i]; - } - } + if (this.Bounds.Width < 0) this.RegisterForLayouting (LayoutingType.Width); } @@ -178,15 +198,10 @@ namespace Crow if (this.Bounds.Height < 0) this.RegisterForLayouting (LayoutingType.Height); } else if (g == tallestChild) { - //search for the new tallest child + tallestChild = null; maxChildrenHeight = 0; - for (int i = 0; i < children.Count; i++) { - if (children [i].Slot.Height > maxChildrenHeight) { - maxChildrenHeight = children [i].Slot.Height; - tallestChild = children [i]; - } - } + if (this.Bounds.Height < 0) this.RegisterForLayouting (LayoutingType.Height); } @@ -194,6 +209,42 @@ namespace Crow } } + //TODO: x,y position should be taken in account for computation of width and height + void resetChildrenMaxSize(){ + largestChild = null; + tallestChild = null; + maxChildrenWidth = 0; + maxChildrenHeight = 0; + } + void searchLargestChild(){ + largestChild = null; + maxChildrenWidth = 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 > maxChildrenWidth) { + maxChildrenWidth = Children [i].Slot.Width; + largestChild = Children [i]; + } + } + } + void searchTallestChild(){ + tallestChild = null; + maxChildrenHeight = 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 > maxChildrenHeight) { + maxChildrenHeight = Children [i].Slot.Height; + tallestChild = Children [i]; + } + } + } + protected override void onDraw (Context gr) { base.onDraw (gr); @@ -203,7 +254,7 @@ namespace Crow CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); gr.Clip (); - foreach (GraphicObject g in children) { + foreach (GraphicObject g in Children) { g.Paint (ref gr); } gr.Restore (); @@ -223,7 +274,7 @@ namespace Crow CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); gr.Clip (); - foreach (GraphicObject c in children) { + foreach (GraphicObject c in Children) { if (!c.Visible) continue; if (Clipping.intersect(c.Slot + ClientRectangle.Position)) @@ -245,17 +296,16 @@ namespace Crow #region Mouse handling - public override void checkHoverWidget (OpenTK.Input.MouseMoveEventArgs e) + public override void checkHoverWidget (MouseMoveEventArgs e) { if (HostContainer.hoverWidget != this) { HostContainer.hoverWidget = this; onMouseEnter (this, e); } - foreach (GraphicObject g in children) - { - if (g.MouseIsIn(e.Position)) + for (int i = Children.Count - 1; i >= 0; i--) { + if (Children[i].MouseIsIn(e.Position)) { - g.checkHoverWidget (e); + Children[i].checkHoverWidget (e); return; } } @@ -263,6 +313,7 @@ namespace Crow } #endregion + #region IXmlSerializable public override System.Xml.Schema.XmlSchema GetSchema() @@ -297,7 +348,7 @@ namespace Crow { base.WriteXml(writer); - foreach (GraphicObject go in children) + foreach (GraphicObject go in Children) { writer.WriteStartElement(go.GetType().Name); (go as IXmlSerializable).WriteXml(writer); @@ -308,7 +359,7 @@ namespace Crow #endregion public override void ClearBinding(){ - foreach (GraphicObject c in children) + foreach (GraphicObject c in Children) c.ClearBinding (); base.ClearBinding (); } diff --git a/src/GraphicObjects/GroupBox.cs b/src/GraphicObjects/GroupBox.cs index 9206792a..e3001663 100644 --- a/src/GraphicObjects/GroupBox.cs +++ b/src/GraphicObjects/GroupBox.cs @@ -1,20 +1,6 @@ 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 Crow { diff --git a/src/GraphicObjects/ILayoutable.cs b/src/GraphicObjects/ILayoutable.cs index bbf1b4a6..51abc25d 100644 --- a/src/GraphicObjects/ILayoutable.cs +++ b/src/GraphicObjects/ILayoutable.cs @@ -19,6 +19,7 @@ namespace Crow IGOLibHost HostContainer { get; } + bool ArrangeChildren { get; } LayoutingType RegisteredLayoutings { get; set; } void RegisterForLayouting(LayoutingType layoutType); void RegisterClip(Rectangle clip); diff --git a/src/GraphicObjects/Image.cs b/src/GraphicObjects/Image.cs index bd6a57c9..6755653e 100644 --- a/src/GraphicObjects/Image.cs +++ b/src/GraphicObjects/Image.cs @@ -94,12 +94,15 @@ namespace Crow #endregion #region GraphicObject overrides - protected override Size measureRawSize () + protected override int measureRawSize (LayoutingType lt) { if (_pic == null) _pic = "#Crow.Images.Icons.IconAlerte.svg"; - - return _pic.Dimensions + Margin * 2; + //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) { diff --git a/src/GraphicObjects/Label.cs b/src/GraphicObjects/Label.cs index 4c7e7006..ad6549a1 100644 --- a/src/GraphicObjects/Label.cs +++ b/src/GraphicObjects/Label.cs @@ -319,13 +319,11 @@ namespace Crow set { base.Height = value; } } - protected override Size measureRawSize() - { - Size size; - + protected override int measureRawSize(LayoutingType lt) + { if (lines == null) lines = getLines; - + using (ImageSurface img = new ImageSurface (Format.Argb32, 10, 10)) { using (Context gr = new Context (img)) { //Cairo.FontFace cf = gr.GetContextFontFace (); @@ -333,8 +331,19 @@ namespace Crow 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.TabSize)); @@ -346,16 +355,9 @@ namespace Crow if (tmp.XAdvance > te.XAdvance) te = tmp; } - fe = gr.FontExtents; - int lc = lines.Count; - //ensure minimal height = text line height - if (lc == 0) - lc = 1; - size = new Size ((int)Math.Ceiling (te.XAdvance) + Margin * 2, (int)(fe.Height * lc) + Margin*2); + return (int)Math.Ceiling (te.XAdvance) + Margin * 2; } } - - return size;; } protected override void onDraw (Context gr) { @@ -368,7 +370,8 @@ namespace Crow //gr.FontOptions.Antialias = Antialias.Subpixel; //gr.FontOptions.HintMetrics = HintMetrics.On; - rText = new Rectangle(measureRawSize()); + rText = new Rectangle(new Size( + measureRawSize(LayoutingType.Width), measureRawSize(LayoutingType.Height))); rText.Width -= 2 * Margin; rText.Height -= 2 * Margin; diff --git a/src/GraphicObjects/Popper.cs b/src/GraphicObjects/Popper.cs index 171e54e4..c99b0889 100644 --- a/src/GraphicObjects/Popper.cs +++ b/src/GraphicObjects/Popper.cs @@ -1,20 +1,7 @@ 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 OpenTK.Input; namespace Crow { diff --git a/src/GraphicObjects/PrivateContainer.cs b/src/GraphicObjects/PrivateContainer.cs index 77bf655f..640e8d0b 100644 --- a/src/GraphicObjects/PrivateContainer.cs +++ b/src/GraphicObjects/PrivateContainer.cs @@ -91,11 +91,35 @@ namespace Crow return child == goToFind ? true : child == null ? false : child.Contains(goToFind); } - protected override Size measureRawSize () - { - return child == null ? Bounds.Size : child.Slot.Size + 2 * Margin; + protected override int measureRawSize (LayoutingType lt) + { + if (child == null) + return base.measureRawSize (lt); + if (lt == LayoutingType.Width) + return child.RegisteredLayoutings.HasFlag(LayoutingType.Width) ? + -1 : child.Slot.Size.Width + 2 * Margin; + else + return child.RegisteredLayoutings.HasFlag(LayoutingType.Height) ? + -1 : child.Slot.Size.Height + 2 * Margin; + } + 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 < 0 && child.Width == 0) + child.Width = -1; + break; + case LayoutingType.Height: + if (Height < 0 && child.Height == 0) + child.Height = -1; + break; + } + } + return base.UpdateLayout (layoutType); } - public override void OnLayoutChanges (LayoutingType layoutType) { base.OnLayoutChanges (layoutType); @@ -212,8 +236,8 @@ namespace Crow { base.checkHoverWidget (e); if (child != null) - if (child.MouseIsIn (e.Position)) - child.checkHoverWidget (e); + if (child.MouseIsIn (e.Position)) + child.checkHoverWidget (e); } #endregion diff --git a/src/GraphicObjects/RadioButton.cs b/src/GraphicObjects/RadioButton.cs index 297b4c2b..4fd45c58 100644 --- a/src/GraphicObjects/RadioButton.cs +++ b/src/GraphicObjects/RadioButton.cs @@ -1,18 +1,7 @@ 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.Serialization; namespace Crow { @@ -31,17 +20,12 @@ namespace Crow public event EventHandler Unchecked; #region GraphicObject overrides - [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to true + [XmlAttributeAttribute()][DefaultValue(true)] public override bool Focusable { get { return base.Focusable; } set { base.Focusable = value; } } - [XmlAttributeAttribute()][DefaultValue(-1)] - public override int Height { - get { return base.Height; } - set { base.Height = value; } - } #endregion [XmlAttributeAttribute()][DefaultValue("RadioButton")] @@ -91,8 +75,12 @@ namespace Crow { Group pg = Parent as Group; if (pg != null) { - foreach (RadioButton c in pg.Children.OfType<RadioButton>()) + 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; diff --git a/src/GraphicObjects/ScrollBar.cs b/src/GraphicObjects/ScrollBar.cs index dddd441e..d1ef12a3 100644 --- a/src/GraphicObjects/ScrollBar.cs +++ b/src/GraphicObjects/ScrollBar.cs @@ -1,18 +1,7 @@ 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 OpenTK.Input; namespace Crow { diff --git a/src/GraphicObjects/Scroller.cs b/src/GraphicObjects/Scroller.cs index 1924aac0..459205fe 100644 --- a/src/GraphicObjects/Scroller.cs +++ b/src/GraphicObjects/Scroller.cs @@ -1,13 +1,30 @@ -using System; +// +// Scroller.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +using System; +using System.Xml.Serialization; +using System.ComponentModel; using System.Diagnostics; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Drawing; using Cairo; -using System.Xml.Serialization; using OpenTK.Input; -using System.ComponentModel; namespace Crow { @@ -95,7 +112,6 @@ namespace Crow } #endregion - public Scroller() : base(){} @@ -192,14 +208,6 @@ namespace Crow { return base.ScreenCoordinates (r) - new Point((int)ScrollX,(int)ScrollY); } -// protected override void onDraw (Context gr) -// { -// gr.Save (); -// //gr.ResetClip (); -// -// base.onDraw (gr); -// gr.Restore (); -// } protected override void onDraw (Context gr) { Rectangle rBack = new Rectangle (Slot.Size); @@ -218,20 +226,5 @@ namespace Crow child.Paint (ref gr); gr.Restore (); } - -// public override void Paint (ref Context ctx) -// { -// ctx.Save (); -// //ctx.ResetClip (); -// ctx.Translate (-ScrollX, -ScrollY); -// base.Paint (ref ctx); -// ctx.Restore (); -// } -// public override void registerClipRect () -// { -// HostContainer.redrawClip.AddRectangle (base.ScreenCoordinates(Slot)); -// } - - } } diff --git a/src/GraphicObjects/Splitter.cs b/src/GraphicObjects/Splitter.cs new file mode 100644 index 00000000..f3fdb341 --- /dev/null +++ b/src/GraphicObjects/Splitter.cs @@ -0,0 +1,114 @@ +// +// Spliter.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; +using System.Xml.Serialization; +using System.ComponentModel; + +namespace Crow +{ + [StyleAttribute("Background", "DimGray")] + public class Splitter : GraphicObject + { + #region CTOR + public Splitter (): base(){} + #endregion + + int thickness; + [XmlAttributeAttribute()][DefaultValue(1)] + public virtual int Thickness { + get { return thickness; } + set { + if (thickness == value) + return; + thickness = value; + NotifyValueChanged ("Thickness", thickness); + RegisterForLayouting (LayoutingType.Sizing); + registerForGraphicUpdate (); + } + } + #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, OpenTK.Input.MouseMoveEventArgs e) + { + base.onMouseEnter (sender, e); + if ((Parent as GenericStack).Orientation == Orientation.Horizontal) + this.HostContainer.MouseCursor = XCursor.H; + else + this.HostContainer.MouseCursor = XCursor.V; + } + public override void onMouseLeave (object sender, OpenTK.Input.MouseMoveEventArgs e) + { + base.onMouseLeave (sender, e); + this.HostContainer.MouseCursor = XCursor.Default; + } + public override void onMouseMove (object sender, OpenTK.Input.MouseMoveEventArgs e) + { + base.onMouseMove (sender, e); + + if (!IsActive) + return; + + GenericStack gs = Parent as GenericStack; + int ptrThis = gs.Children.IndexOf (this); + + if (gs.Orientation == Orientation.Horizontal) { + if (ptrThis >= 0) + gs.Children [ptrThis - 1].Width = Math.Max(gs.Children [ptrThis - 1].Slot.Width + e.XDelta*2, 1); + if (ptrThis < gs.Children.Count - 1) + gs.Children [ptrThis + 1].Width = Math.Max(gs.Children [ptrThis + 1].Slot.Width - e.XDelta*2, 1); + } else { + if (ptrThis >= 0) + gs.Children [ptrThis - 1].Height = Math.Max(gs.Children [ptrThis - 1].Slot.Height + e.YDelta*2, 1); + if (ptrThis < gs.Children.Count - 1) + gs.Children [ptrThis + 1].Height = Math.Max(gs.Children [ptrThis + 1].Slot.Height - e.YDelta*2, 1); + } + } + public override bool UpdateLayout (LayoutingType layoutType) + { + GenericStack gs = Parent as GenericStack; + if (layoutType == LayoutingType.Width){ + if (gs.Orientation == Orientation.Horizontal) + Width = thickness; + else + Width = 0; + } else if (layoutType == LayoutingType.Height){ + if (gs.Orientation == Orientation.Vertical) + Height = thickness; + else + Height = 0; + } + return base.UpdateLayout (layoutType); + } + #endregion + } +} + diff --git a/src/GraphicObjects/TabItem.cs b/src/GraphicObjects/TabItem.cs new file mode 100644 index 00000000..b0e733fb --- /dev/null +++ b/src/GraphicObjects/TabItem.cs @@ -0,0 +1,216 @@ +// +// TabItem.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; +using System.Xml.Serialization; +using System.ComponentModel; +using System.Diagnostics; + +namespace Crow +{ + [DefaultTemplate("#Crow.Templates.TabItem.crow")] + public class TabItem : TemplatedContainer + { + #region Private fields + string caption; + Container _contentContainer; + GraphicObject _tabTitle; + int tabOffset; + #endregion + + #region CTOR + public TabItem () : base() + { + } + #endregion + + #region TemplatedControl overrides + public override GraphicObject Content { + get { + return _contentContainer == null ? null : _contentContainer.Child; + } + set { + _contentContainer.SetChild(value); + } + } + public override void ResolveBindings () + { + base.ResolveBindings (); + if (_contentContainer != null) + _contentContainer.ResolveBindings (); + } + protected override void loadTemplate(GraphicObject template = null) + { + base.loadTemplate (template); + + _contentContainer = this.child.FindByName ("Content") as Container; + _tabTitle = this.child.FindByName ("TabTitle"); + } + internal GraphicObject TabTitle { get { return _tabTitle; }} + #endregion + + #region GraphicObject overrides + [XmlAttributeAttribute()][DefaultValue(true)] + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + //prevent caching, because drawing order is different depending on selected tab + [XmlAttributeAttribute()][DefaultValue(false)] + public override bool CacheEnabled { + get {return false;} + set { } + } + #endregion + + [XmlAttributeAttribute()][DefaultValue(0)] + public virtual int TabOffset { + get { return tabOffset; } + set { + if (tabOffset == value) + return; + tabOffset = value; + NotifyValueChanged ("TabOffset", tabOffset); + + RegisterForLayouting (LayoutingType.X); + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue("TabItem")] + public string Caption { + get { return caption; } + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + bool isSelected; + [XmlAttributeAttribute()][DefaultValue(false)] + public virtual bool IsSelected { + get { return isSelected; } + set { + if (isSelected == value) + return; + isSelected = value; + NotifyValueChanged ("IsSelected", isSelected); + } + } + protected override void onDraw (Cairo.Context gr) + { + int spacing = (Parent as TabView).Spacing; + gr.MoveTo (0, TabTitle.Slot.Bottom); + gr.LineTo (TabTitle.Slot.Left - spacing, TabTitle.Slot.Bottom); + gr.CurveTo ( + TabTitle.Slot.Left - spacing / 2, TabTitle.Slot.Bottom, + TabTitle.Slot.Left - spacing / 2, 1, + TabTitle.Slot.Left, 1); + gr.LineTo (TabTitle.Slot.Right, 1); + gr.CurveTo ( + TabTitle.Slot.Right + spacing / 2, 1, + TabTitle.Slot.Right + spacing / 2, TabTitle.Slot.Bottom, + TabTitle.Slot.Right + spacing, TabTitle.Slot.Bottom); + gr.LineTo (Slot.Width, TabTitle.Slot.Bottom); + + gr.LineWidth = 1; + Foreground.SetAsSource (gr); + gr.StrokePreserve (); + + gr.LineTo (Slot.Width, Slot.Height); + gr.LineTo (0, Slot.Height); + gr.ClosePath (); + gr.Save (); + gr.Clip (); + base.onDraw (gr); + gr.Restore (); + } + + #region Mouse Handling + public override bool MouseIsIn (Point m) + { + if (!Visible) + return false; + + bool mouseIsInTitle = TabTitle.ScreenCoordinates (TabTitle.Slot).ContainsOrIsEqual (m); + if (!IsSelected) + return mouseIsInTitle; + + return _contentContainer.ScreenCoordinates (_contentContainer.Slot).ContainsOrIsEqual (m) + || mouseIsInTitle; + } + bool holdCursor = false; + public override void onMouseDown (object sender, OpenTK.Input.MouseButtonEventArgs e) + { + base.onMouseDown (sender, e); + holdCursor = true; + } + public override void onMouseUp (object sender, OpenTK.Input.MouseButtonEventArgs e) + { + base.onMouseUp (sender, e); + holdCursor = false; + (Parent as TabView).UpdateLayout (LayoutingType.ArrangeChildren); + } + public override void onMouseMove (object sender, OpenTK.Input.MouseMoveEventArgs e) + { + base.onMouseMove (sender, e); + + if (!(HasFocus&&holdCursor)) + return; + TabView tv = Parent as TabView; + TabItem previous = null, next = null; + int tmp = TabOffset + e.XDelta; + if (tmp < tv.Spacing) + TabOffset = tv.Spacing; + else if (tmp > Parent.getSlot ().Width - TabTitle.Slot.Width - tv.Spacing) + TabOffset = Parent.getSlot ().Width - TabTitle.Slot.Width - tv.Spacing; + else{ + int idx = tv.Children.IndexOf (this); + if (idx > 0 && e.XDelta < 0) { + previous = tv.Children [idx - 1] as TabItem; + + if (tmp < previous.TabOffset + previous.TabTitle.Slot.Width / 2) { + tv.Children.RemoveAt (idx); + tv.Children.Insert (idx - 1, this); + tv.SelectedTab = idx - 1; + tv.UpdateLayout (LayoutingType.ArrangeChildren); + } + + }else if (idx < tv.Children.Count - 1 && e.XDelta > 0) { + next = tv.Children [idx + 1] as TabItem; + if (tmp > next.TabOffset - next.TabTitle.Slot.Width / 2){ + tv.Children.RemoveAt (idx); + tv.Children.Insert (idx + 1, this); + tv.SelectedTab = idx + 1; + tv.UpdateLayout (LayoutingType.ArrangeChildren); + } + } + TabOffset = tmp; + } + } + public void butCloseTabClick (object sender, OpenTK.Input.MouseButtonEventArgs e){ + (Parent as TabView).RemoveChild(this); + } + #endregion + + } +} + diff --git a/src/GraphicObjects/TabView.cs b/src/GraphicObjects/TabView.cs new file mode 100644 index 00000000..a480ae09 --- /dev/null +++ b/src/GraphicObjects/TabView.cs @@ -0,0 +1,216 @@ +// +// TabView.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; +using System.Xml.Serialization; +using System.ComponentModel; +using Cairo; +using System.Diagnostics; +using OpenTK.Input; + +namespace Crow +{ + public class TabView : Group + { + #region Private fields + int _spacing; + Orientation _orientation; + int selectedTab = 0; + #endregion + + public TabView () : base() + { + } + + [XmlAttributeAttribute()][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); + } + } + [XmlAttributeAttribute()][DefaultValue(2)] + public int Spacing + { + get { return _spacing; } + set { + if (_spacing == value) + return; + _spacing = value; + NotifyValueChanged ("Spacing", Spacing); + } + } + [XmlAttributeAttribute()][DefaultValue(0)] + public virtual int SelectedTab { + get { return selectedTab; } + set { + 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); + registerForGraphicUpdate (); + } + } + int tabThickness; + [XmlAttributeAttribute()][DefaultValue(22)] + public virtual int TabThickness { + get { return tabThickness; } + set { + if (tabThickness == value) + return; + tabThickness = value; + NotifyValueChanged ("TabThickness", tabThickness); + } + } + + //prevent caching, because drawing order is different depending on selected tab + [XmlAttributeAttribute()][DefaultValue(false)] + public override bool CacheEnabled { + get {return false;} + set { } + } + + public override T AddChild<T> (T child) + { + TabItem ti = child as TabItem; + if (ti == null) + throw new Exception ("TabView control accept only TabItem as child."); + + ti.MouseDown += Ti_MouseDown; + + if (Children.Count == 0) { + ti.IsSelected = true; + SelectedTab = 0; + } + + return base.AddChild (child); + } + public override void RemoveChild (GraphicObject child) + { + int idx = Children.IndexOf (child); + base.RemoveChild (child); + if (selectedTab > Children.Count - 1) + SelectedTab--; + else + SelectedTab = selectedTab; + } + public override bool ArrangeChildren { get { return true; } } + public override bool UpdateLayout (LayoutingType layoutType) + { + RegisteredLayoutings &= (~layoutType); + + if (layoutType == LayoutingType.ArrangeChildren) { + int curOffset = Spacing; + for (int i = 0; i < Children.Count; i++) { + if (!Children [i].Visible) + continue; + TabItem ti = Children [i] as TabItem; + ti.TabOffset = curOffset; + if (Orientation == Orientation.Horizontal) { + if (ti.TabTitle.RegisteredLayoutings.HasFlag (LayoutingType.Width)) + return false; + curOffset += ti.TabTitle.Slot.Width + Spacing; + } else { + if (ti.TabTitle.RegisteredLayoutings.HasFlag (LayoutingType.Height)) + return false; + curOffset += ti.TabTitle.Slot.Height + Spacing; + } + } + + //if no layouting remains in queue for item, registre for redraw + if (RegisteredLayoutings == LayoutingType.None && bmp==null) + this.RegisterForRedraw (); + + return true; + } + + return base.UpdateLayout(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 (); + //clip to client zone + CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); + gr.Clip (); + + for (int i = 0; i < Children.Count; i++) { + if (i == SelectedTab) + continue; + Children [i].Paint (ref gr); + } + + if (SelectedTab < Children.Count && SelectedTab >= 0) + Children [SelectedTab].Paint (ref gr); + + gr.Restore (); + } + + #region Mouse handling + public override void checkHoverWidget (MouseMoveEventArgs e) + { + if (HostContainer.hoverWidget != this) { + HostContainer.hoverWidget = this; + onMouseEnter (this, e); + } + + if (SelectedTab > Children.Count - 1) + return; + + if (((Children[SelectedTab] as TabItem).Content.Parent as GraphicObject).MouseIsIn(e.Position)) + { + Children[SelectedTab].checkHoverWidget (e); + return; + } + for (int i = Children.Count - 1; i >= 0; i--) { + TabItem ti = Children [i] as TabItem; + if (ti.TabTitle.MouseIsIn(e.Position)) + { + Children[i].checkHoverWidget (e); + return; + } + } + } + #endregion + void Ti_MouseDown (object sender, OpenTK.Input.MouseButtonEventArgs e) + { + SelectedTab = Children.IndexOf (sender as GraphicObject); + } + } +} + diff --git a/src/GraphicObjects/TemplatedControl.cs b/src/GraphicObjects/TemplatedControl.cs index 50199f7a..75176c34 100644 --- a/src/GraphicObjects/TemplatedControl.cs +++ b/src/GraphicObjects/TemplatedControl.cs @@ -38,6 +38,16 @@ namespace Crow } } [AttributeUsage(AttributeTargets.Class)] + public class StyleAttribute : Attribute + { + public string PropertyName = ""; + public object DefaultValue = null; + public StyleAttribute(string _property, object _defValue){ + PropertyName = _property; + DefaultValue = _defValue; + } + } + [AttributeUsage(AttributeTargets.Class)] public class DefaultTemplate : TemplateAttribute { public DefaultTemplate(string path) : base(path){} @@ -61,38 +71,47 @@ namespace Crow string _template; - [XmlAttributeAttribute][DefaultValue("#Crow.Templates.Template.goml")] + [XmlAttributeAttribute][DefaultValue(null)] public string Template { get { return _template; } - set { _template = value; } - } + set { + if (Template == value) + return; + _template = value; - #region GraphicObject overrides - [XmlAttributeAttribute()][DefaultValue(-1)] - public override int Width { - get { return base.Width; } - set { - base.Width = value; - //PropertyLess binding for sizing policy in template - if (base.Width < 1) //send size policy to template elements - NotifyValueChanged ("TemplatedWidth", base.Width); - else //stretched in control if size is fixed - NotifyValueChanged ("TemplatedWidth", 0); + if (string.IsNullOrEmpty(_template)) + loadTemplate (); + else + loadTemplate (Interface.Load (_template, this)); } } - [XmlAttributeAttribute()][DefaultValue(-1)] - public override int Height { - get { return base.Height; } - set { - base.Height = value; - //PropertyLess binding for sizing policy in template - if (base.Height < 1) //send size policy to template elements - NotifyValueChanged ("TemplatedHeight", base.Height); - else //stretched in control if size is fixed - NotifyValueChanged ("TemplatedHeight", 0); - } - } + #region GraphicObject overrides +// [XmlAttributeAttribute()][DefaultValue(-1)] +// public override int Width { +// get { return base.Width; } +// set { +// base.Width = value; +// //PropertyLess binding for sizing policy in template +// if (base.Width < 1) //send size policy to template elements +// NotifyValueChanged ("TemplatedWidth", base.Width); +// else //stretched in control if size is fixed +// NotifyValueChanged ("TemplatedWidth", 0); +// } +// } +// [XmlAttributeAttribute()][DefaultValue(-1)] +// public override int Height { +// get { return base.Height; } +// set { +// base.Height = value; +// +// //PropertyLess binding for sizing policy in template +// if (base.Height < 1) //send size policy to template elements +// NotifyValueChanged ("TemplatedHeight", base.Height); +// else //stretched in control if size is fixed +// NotifyValueChanged ("TemplatedHeight", 0); +// } +// } public override GraphicObject FindByName (string nameToFind) { //prevent name searching in template diff --git a/src/GraphicObjects/TextRun.cs b/src/GraphicObjects/TextRun.cs index a426bdee..bb308eb6 100644 --- a/src/GraphicObjects/TextRun.cs +++ b/src/GraphicObjects/TextRun.cs @@ -144,13 +144,11 @@ namespace Crow set { base.Margin = value; } } - protected override Size measureRawSize() - { - Size size; - + protected override int measureRawSize(LayoutingType lt) + { if (lines == null) lines = getLines; - + using (ImageSurface img = new ImageSurface (Format.Argb32, 10, 10)) { using (Context gr = new Context (img)) { //Cairo.FontFace cf = gr.GetContextFontFace (); @@ -158,30 +156,34 @@ namespace Crow 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.TabSize)); -#if _WIN32 || _WIN64 + #if _WIN32 || _WIN64 TextExtents tmp = gr.TextExtents(str.ToUtf8()); -#elif __linux__ + #elif __linux__ TextExtents tmp = gr.TextExtents (l); -#endif + #endif if (tmp.XAdvance > te.XAdvance) te = tmp; } - fe = gr.FontExtents; - int lc = lines.Count; - //ensure minimal height = text line height - if (lc == 0) - lc = 1; - size = new Size ((int)Math.Ceiling (te.XAdvance) + Margin * 2, (int)(fe.Height * lc) + Margin*2); + return (int)Math.Ceiling (te.XAdvance) + Margin * 2; } } - - return size;; - } + } protected override void onDraw (Context gr) { base.onDraw (gr); @@ -193,7 +195,8 @@ namespace Crow //gr.FontOptions.Antialias = Antialias.Subpixel; //gr.FontOptions.HintMetrics = HintMetrics.On; - rText = new Rectangle(measureRawSize()); + rText = new Rectangle(new Size( + measureRawSize(LayoutingType.Width), measureRawSize(LayoutingType.Height))); rText.Width -= 2 * Margin; rText.Height -= 2 * Margin; diff --git a/src/GraphicObjects/TreeView.cs b/src/GraphicObjects/TreeView.cs new file mode 100644 index 00000000..64d4afcb --- /dev/null +++ b/src/GraphicObjects/TreeView.cs @@ -0,0 +1,35 @@ +// +// TreeView.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; + +namespace Crow +{ + //treeview expect expandable child (or not) + //if their are expandable, some functions and events are added + [DefaultTemplate("#Crow.Templates.TreeView.crow")] + public class TreeView : ListBox + { + public TreeView () : base() + { + } + } +} + |