diff options
| author | jpbruyere <jp.bruyere@hotmail.com> | 2016-02-02 12:19:06 +0100 |
|---|---|---|
| committer | jpbruyere <jp.bruyere@hotmail.com> | 2016-02-02 12:19:06 +0100 |
| commit | 2b087282dd73152d21140ea7312a90e046c84f61 (patch) | |
| tree | 5d03225090e39c1d14465bdbaf1882e87026402b /src/GraphicObjects | |
| parent | 73b7c1d82226e4d10708e858a011991e3f598655 (diff) | |
Fix CRLF
Diffstat (limited to 'src/GraphicObjects')
24 files changed, 5358 insertions, 5358 deletions
diff --git a/src/GraphicObjects/Button.cs b/src/GraphicObjects/Button.cs index 17fbe328..5bf11f68 100644 --- a/src/GraphicObjects/Button.cs +++ b/src/GraphicObjects/Button.cs @@ -1,105 +1,105 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-//using OpenTK.Graphics.OpenGL;
-
-using System.Diagnostics;
-
-using System.Xml.Serialization;
-using Cairo;
-using OpenTK.Input;
-using System.ComponentModel;
-
-namespace Crow
-{
- [DefaultTemplate("#Crow.Templates.Button.crow")]
- public class Button : TemplatedContainer
- {
- #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;
- string image;
- Container _contentContainer;
-
- public override GraphicObject Content {
- get {
- return _contentContainer == null ? null : _contentContainer.Child;
- }
- set {
- if (_contentContainer != null)
- _contentContainer.SetChild(value);
- }
- }
- protected override void loadTemplate(GraphicObject template = null)
- {
- base.loadTemplate (template);
-
- _contentContainer = this.child.FindByName ("Content") as Container;
- }
-
- #region GraphicObject Overrides
-// [XmlAttributeAttribute()][DefaultValue(50)]
-// public override int Width {
-// get { return base.Width; }
-// set { base.Width = value; }
-// }
-// [XmlAttributeAttribute()][DefaultValue(20)]
-// public override int Height {
-// get { return base.Height; }
-// set { base.Height = value; }
-// }
- [XmlAttributeAttribute()][DefaultValue(true)]
- public override bool Focusable
- {
- get { return base.Focusable; }
- set { base.Focusable = value; }
- }
- public override void ResolveBindings ()
- {
- base.ResolveBindings ();
- if (Content != null)
- Content.ResolveBindings ();
- }
- public override void onMouseDown (object sender, MouseButtonEventArgs e)
- {
- base.onMouseDown (sender, e);
- NotifyValueChanged ("State", "pressed");
- }
- public override void onMouseUp (object sender, MouseButtonEventArgs e)
- {
- base.onMouseUp (sender, e);
- NotifyValueChanged ("State", "normal");
- }
- #endregion
-
- [XmlAttributeAttribute()][DefaultValue("Button")]
- public string Caption {
- get { return caption; }
- set {
- if (caption == value)
- return;
- caption = value;
- NotifyValueChanged ("Caption", caption);
- }
- }
- [XmlAttributeAttribute()][DefaultValue("#Crow.Images.button.svg")]
- public string Image {
- get { return image; }
- set {
- if (image == value)
- return;
- image = value;
- NotifyValueChanged ("Image", image);
- }
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +//using OpenTK.Graphics.OpenGL; + +using System.Diagnostics; + +using System.Xml.Serialization; +using Cairo; +using OpenTK.Input; +using System.ComponentModel; + +namespace Crow +{ + [DefaultTemplate("#Crow.Templates.Button.crow")] + public class Button : TemplatedContainer + { + #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; + string image; + Container _contentContainer; + + public override GraphicObject Content { + get { + return _contentContainer == null ? null : _contentContainer.Child; + } + set { + if (_contentContainer != null) + _contentContainer.SetChild(value); + } + } + protected override void loadTemplate(GraphicObject template = null) + { + base.loadTemplate (template); + + _contentContainer = this.child.FindByName ("Content") as Container; + } + + #region GraphicObject Overrides +// [XmlAttributeAttribute()][DefaultValue(50)] +// public override int Width { +// get { return base.Width; } +// set { base.Width = value; } +// } +// [XmlAttributeAttribute()][DefaultValue(20)] +// public override int Height { +// get { return base.Height; } +// set { base.Height = value; } +// } + [XmlAttributeAttribute()][DefaultValue(true)] + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + public override void ResolveBindings () + { + base.ResolveBindings (); + if (Content != null) + Content.ResolveBindings (); + } + public override void onMouseDown (object sender, MouseButtonEventArgs e) + { + base.onMouseDown (sender, e); + NotifyValueChanged ("State", "pressed"); + } + public override void onMouseUp (object sender, MouseButtonEventArgs e) + { + base.onMouseUp (sender, e); + NotifyValueChanged ("State", "normal"); + } + #endregion + + [XmlAttributeAttribute()][DefaultValue("Button")] + public string Caption { + get { return caption; } + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + [XmlAttributeAttribute()][DefaultValue("#Crow.Images.button.svg")] + public string Image { + get { return image; } + set { + if (image == value) + return; + image = value; + NotifyValueChanged ("Image", image); + } + } + } +} diff --git a/src/GraphicObjects/CheckBox.cs b/src/GraphicObjects/CheckBox.cs index a08f9fdb..fa34522d 100644 --- a/src/GraphicObjects/CheckBox.cs +++ b/src/GraphicObjects/CheckBox.cs @@ -1,94 +1,94 @@ -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;
-
-namespace Crow
-{
- [DefaultTemplate("#Crow.Templates.CheckBox.goml")]
- public class CheckBox : TemplatedControl
- {
- string caption;
- string image;
- bool isChecked;
-
- #region CTOR
- public CheckBox() : base()
- {
- }
- #endregion
-
- public event EventHandler Checked;
- 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
- public override bool Focusable
- {
- get { return base.Focusable; }
- set { base.Focusable = value; }
- }
- #endregion
-
- [XmlAttributeAttribute()][DefaultValue("Checkbox")]
- public string Caption {
- get { return caption; }
- set {
- if (caption == value)
- return;
- caption = value;
- NotifyValueChanged ("Caption", caption);
- }
- }
- [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.checkbox.svg")]
- public string Image {
- get { return image; }
- set {
- if (image == value)
- return;
- image = value;
- NotifyValueChanged ("Image", image);
- }
- }
-
- [XmlAttributeAttribute()][DefaultValue(false)]
- public bool IsChecked
- {
- get { return isChecked; }
- set
- {
- isChecked = value;
-
- NotifyValueChanged ("IsChecked", value);
- if (isChecked) {
- NotifyValueChanged ("SvgSub", "checked");
- Checked.Raise (this, null);
- } else {
- NotifyValueChanged ("SvgSub", "unchecked");
- Unchecked.Raise (this, null);
- }
- }
- }
- public override void onMouseClick (object sender, MouseButtonEventArgs e)
- {
- IsChecked = !IsChecked;
- base.onMouseClick (sender, e);
- }
- }
-}
+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; + +namespace Crow +{ + [DefaultTemplate("#Crow.Templates.CheckBox.goml")] + public class CheckBox : TemplatedControl + { + string caption; + string image; + bool isChecked; + + #region CTOR + public CheckBox() : base() + { + } + #endregion + + public event EventHandler Checked; + 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 + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + #endregion + + [XmlAttributeAttribute()][DefaultValue("Checkbox")] + public string Caption { + get { return caption; } + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.checkbox.svg")] + public string Image { + get { return image; } + set { + if (image == value) + return; + image = value; + NotifyValueChanged ("Image", image); + } + } + + [XmlAttributeAttribute()][DefaultValue(false)] + public bool IsChecked + { + get { return isChecked; } + set + { + isChecked = value; + + NotifyValueChanged ("IsChecked", value); + if (isChecked) { + NotifyValueChanged ("SvgSub", "checked"); + Checked.Raise (this, null); + } else { + NotifyValueChanged ("SvgSub", "unchecked"); + Unchecked.Raise (this, null); + } + } + } + public override void onMouseClick (object sender, MouseButtonEventArgs e) + { + IsChecked = !IsChecked; + base.onMouseClick (sender, e); + } + } +} diff --git a/src/GraphicObjects/ComboBox.cs b/src/GraphicObjects/ComboBox.cs index b958a81b..ed979d75 100644 --- a/src/GraphicObjects/ComboBox.cs +++ b/src/GraphicObjects/ComboBox.cs @@ -1,365 +1,365 @@ -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;
-using System.Threading;
-
-namespace Crow
-{
- [DefaultTemplate("#Crow.Templates.ComboBox.goml")]
- [DefaultOverlayTemplate("#Crow.Templates.ComboBoxOverlay.goml")]
- public class ComboBox : TemplatedContainer
- {
- #region CTOR
- public ComboBox() : base(){ }
- #endregion
-
- bool _isPopped;
- string caption;
- GraphicObject _overlay;
- Group _list;
- IList data;
- int _selectedIndex;
- object _selectedItem;
- string _itemTemplate;
- string _overlayTemplate;
-
- public event EventHandler Pop;
- public event EventHandler Unpop;
- public event EventHandler<SelectionChangeEventArgs> 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);
- Overlay.ResolveBindings ();
- } else
- Overlay = overlayTemplate;
- _list = Overlay.FindByName ("List") as Group;
- }
-
- [XmlAttributeAttribute][DefaultValue("#Crow.Templates.ItemTemplate.goml")]
- public string ItemTemplate {
- get { return _itemTemplate; }
- set {
- //TODO:reload list with new template?
- _itemTemplate = value;
- }
- }
- [XmlAttributeAttribute][DefaultValue("#Crow.Templates.ComboBoxOverlay.goml")]
- public string OverlayTemplate {
- get { return _overlayTemplate; }
- set {
- //TODO:reload list with new template?
- _overlayTemplate = value;
-
- Overlay = Interface.Load (_overlayTemplate);
- Overlay.ResolveBindings ();
- _list = Overlay.FindByName ("List") as Group;
- }
- }
- [XmlAttributeAttribute][DefaultValue(-1)]
- public int SelectedIndex{
- get { return _selectedIndex; }
- set {
- //store value event if data is null, because in xml parsing selindex is always
- //before data, so it's impossible without that trick to set a default index in goml
- _selectedIndex = value;
-
- if (data == null)
- return;
-
- if (_selectedIndex > data.Count - 1 || _selectedIndex < 0)
- throw new Exception ("Combobox SelectedIndex out of range");
-
-
- _selectedItem = data [_selectedIndex];
- NotifyValueChanged ("SelectedIndex", SelectedIndex);
- SelectedItemChanged.Raise (this, new SelectionChangeEventArgs(_selectedItem));
-
- if (SelectedItem == null)
- Caption = "";
- else
- Caption = _selectedItem.ToString ();
- }
- }
- public object SelectedItem{
- set {
- if (_selectedItem == value)
- return;
-
- _selectedItem = value;
- _selectedIndex = data.IndexOf (_selectedItem);
- NotifyValueChanged ("SelectedIndex", _selectedIndex);
- SelectedItemChanged.Raise (this, new SelectionChangeEventArgs(_selectedItem));
-
- if (SelectedItem == null)
- Caption = "";
- else
- Caption = _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 (SelectedIndex < 0)
- return;
-
- //force raise of changes
- SelectedIndex = SelectedIndex;
-
- pendingChildrenAddition = new Queue<GraphicObject> ();
- threadedLoadingFinished = false;
-
- Thread t = new Thread (loadingThread);
- t.Start ();
- t.Join ();
-
- }
- }
- public override void UpdateLayout (LayoutingType layoutType)
- {
- CheckPendingChildrenAddition ();
- base.UpdateLayout (layoutType);
- }
- internal void CheckPendingChildrenAddition()
- {
- if (pendingChildrenAddition == null)
- return;
- lock (pendingChildrenAddition) {
- if (!threadedLoadingFinished && pendingChildrenAddition.Count < 50)
- return;
- while (pendingChildrenAddition.Count > 0) {
- _list.addChild (pendingChildrenAddition.Dequeue ());
- }
- }
- }
-
- volatile Queue<GraphicObject> pendingChildrenAddition;
- volatile bool threadedLoadingFinished = false;
-
- void loadingThread()
- {
- #if DEBUG_LOAD_TIME
- Stopwatch loadingTime = new Stopwatch ();
- loadingTime.Start ();
- #endif
-
- MemoryStream ms = new MemoryStream ();
- lock (ItemTemplate) {
- 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);
- g.DataSource = item;
- g.MouseClick += itemClick;
-
- lock (pendingChildrenAddition) {
- pendingChildrenAddition.Enqueue (g);
- }
- }
-
- ms.Dispose ();
-
- threadedLoadingFinished = true;
-
- #if DEBUG_LOAD_TIME
- loadingTime.Stop ();
- Debug.WriteLine("Listbox {2} Loading: {0} ticks \t, {1} ms",
- loadingTime.ElapsedTicks,
- loadingTime.ElapsedMilliseconds, this.ToString());
- #endif
- }
- public GraphicObject Overlay {
- get { return _overlay; }
- set {
- if (_overlay != null) {
- _overlay.LayoutChanged -= _overlay_LayoutChanged;
- _overlay.MouseLeave -= _overlay_MouseLeave;
- _overlay.LogicalParent = null;
- }
-
- _overlay = value;
-
- if (_overlay == null)
- return;
-
- _overlay.LogicalParent = this;
- _overlay.Focusable = true;
- _overlay.LayoutChanged += _overlay_LayoutChanged;
- _overlay.MouseLeave += _overlay_MouseLeave;
- }
- }
- [XmlAttributeAttribute()][DefaultValue("Combobox")]
- public string Caption {
- get { return caption; }
- set {
- if (caption == value)
- return;
- caption = value;
- NotifyValueChanged ("Caption", caption);
- }
- }
- [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");
- }
- }
-
- void itemClick(object sender, OpenTK.Input.MouseButtonEventArgs e){
- object datasource = (sender as GraphicObject).DataSource;
- SelectedItem = datasource;
- IsPopped = false;
- //Debug.WriteLine ((sender as GraphicObject).DataSource);
- }
- void _overlay_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;
- }
- }
-
- [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to true
- public override bool Focusable
- {
- get { return base.Focusable; }
- set { base.Focusable = value; }
- }
-
-
- public virtual void onPop(object sender, EventArgs e)
- {
- IGOLibHost tc = HostContainer;
- 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 = HostContainer;
- 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);
- }
-
- 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 ();
-
- }
- public override void ResolveBindings ()
- {
- base.ResolveBindings ();
- if (Overlay != null)
- Overlay.ResolveBindings ();
- }
- }
-}
+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; +using System.Threading; + +namespace Crow +{ + [DefaultTemplate("#Crow.Templates.ComboBox.goml")] + [DefaultOverlayTemplate("#Crow.Templates.ComboBoxOverlay.goml")] + public class ComboBox : TemplatedContainer + { + #region CTOR + public ComboBox() : base(){ } + #endregion + + bool _isPopped; + string caption; + GraphicObject _overlay; + Group _list; + IList data; + int _selectedIndex; + object _selectedItem; + string _itemTemplate; + string _overlayTemplate; + + public event EventHandler Pop; + public event EventHandler Unpop; + public event EventHandler<SelectionChangeEventArgs> 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); + Overlay.ResolveBindings (); + } else + Overlay = overlayTemplate; + _list = Overlay.FindByName ("List") as Group; + } + + [XmlAttributeAttribute][DefaultValue("#Crow.Templates.ItemTemplate.goml")] + public string ItemTemplate { + get { return _itemTemplate; } + set { + //TODO:reload list with new template? + _itemTemplate = value; + } + } + [XmlAttributeAttribute][DefaultValue("#Crow.Templates.ComboBoxOverlay.goml")] + public string OverlayTemplate { + get { return _overlayTemplate; } + set { + //TODO:reload list with new template? + _overlayTemplate = value; + + Overlay = Interface.Load (_overlayTemplate); + Overlay.ResolveBindings (); + _list = Overlay.FindByName ("List") as Group; + } + } + [XmlAttributeAttribute][DefaultValue(-1)] + public int SelectedIndex{ + get { return _selectedIndex; } + set { + //store value event if data is null, because in xml parsing selindex is always + //before data, so it's impossible without that trick to set a default index in goml + _selectedIndex = value; + + if (data == null) + return; + + if (_selectedIndex > data.Count - 1 || _selectedIndex < 0) + throw new Exception ("Combobox SelectedIndex out of range"); + + + _selectedItem = data [_selectedIndex]; + NotifyValueChanged ("SelectedIndex", SelectedIndex); + SelectedItemChanged.Raise (this, new SelectionChangeEventArgs(_selectedItem)); + + if (SelectedItem == null) + Caption = ""; + else + Caption = _selectedItem.ToString (); + } + } + public object SelectedItem{ + set { + if (_selectedItem == value) + return; + + _selectedItem = value; + _selectedIndex = data.IndexOf (_selectedItem); + NotifyValueChanged ("SelectedIndex", _selectedIndex); + SelectedItemChanged.Raise (this, new SelectionChangeEventArgs(_selectedItem)); + + if (SelectedItem == null) + Caption = ""; + else + Caption = _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 (SelectedIndex < 0) + return; + + //force raise of changes + SelectedIndex = SelectedIndex; + + pendingChildrenAddition = new Queue<GraphicObject> (); + threadedLoadingFinished = false; + + Thread t = new Thread (loadingThread); + t.Start (); + t.Join (); + + } + } + public override void UpdateLayout (LayoutingType layoutType) + { + CheckPendingChildrenAddition (); + base.UpdateLayout (layoutType); + } + internal void CheckPendingChildrenAddition() + { + if (pendingChildrenAddition == null) + return; + lock (pendingChildrenAddition) { + if (!threadedLoadingFinished && pendingChildrenAddition.Count < 50) + return; + while (pendingChildrenAddition.Count > 0) { + _list.addChild (pendingChildrenAddition.Dequeue ()); + } + } + } + + volatile Queue<GraphicObject> pendingChildrenAddition; + volatile bool threadedLoadingFinished = false; + + void loadingThread() + { + #if DEBUG_LOAD_TIME + Stopwatch loadingTime = new Stopwatch (); + loadingTime.Start (); + #endif + + MemoryStream ms = new MemoryStream (); + lock (ItemTemplate) { + 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); + g.DataSource = item; + g.MouseClick += itemClick; + + lock (pendingChildrenAddition) { + pendingChildrenAddition.Enqueue (g); + } + } + + ms.Dispose (); + + threadedLoadingFinished = true; + + #if DEBUG_LOAD_TIME + loadingTime.Stop (); + Debug.WriteLine("Listbox {2} Loading: {0} ticks \t, {1} ms", + loadingTime.ElapsedTicks, + loadingTime.ElapsedMilliseconds, this.ToString()); + #endif + } + public GraphicObject Overlay { + get { return _overlay; } + set { + if (_overlay != null) { + _overlay.LayoutChanged -= _overlay_LayoutChanged; + _overlay.MouseLeave -= _overlay_MouseLeave; + _overlay.LogicalParent = null; + } + + _overlay = value; + + if (_overlay == null) + return; + + _overlay.LogicalParent = this; + _overlay.Focusable = true; + _overlay.LayoutChanged += _overlay_LayoutChanged; + _overlay.MouseLeave += _overlay_MouseLeave; + } + } + [XmlAttributeAttribute()][DefaultValue("Combobox")] + public string Caption { + get { return caption; } + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + [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"); + } + } + + void itemClick(object sender, OpenTK.Input.MouseButtonEventArgs e){ + object datasource = (sender as GraphicObject).DataSource; + SelectedItem = datasource; + IsPopped = false; + //Debug.WriteLine ((sender as GraphicObject).DataSource); + } + void _overlay_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; + } + } + + [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to true + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + + + public virtual void onPop(object sender, EventArgs e) + { + IGOLibHost tc = HostContainer; + 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 = HostContainer; + 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); + } + + 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 (); + + } + public override void ResolveBindings () + { + base.ResolveBindings (); + if (Overlay != null) + Overlay.ResolveBindings (); + } + } +} diff --git a/src/GraphicObjects/Container.cs b/src/GraphicObjects/Container.cs index 144eb764..360eee51 100644 --- a/src/GraphicObjects/Container.cs +++ b/src/GraphicObjects/Container.cs @@ -1,78 +1,78 @@ -using System;
-using System.Xml.Serialization;
-using System.Reflection;
-using OpenTK.Input;
-using System.ComponentModel;
-using System.Linq;
-
-namespace Crow
-{
- public class Container : PrivateContainer, IXmlSerializable
- {
- #region CTOR
- public Container()
- : base()
- {
- }
- public Container(Rectangle _bounds)
- : base(_bounds)
- {
- }
- #endregion
-
- [XmlIgnore]
- public GraphicObject Child {
- get { return child; }
- set { child = value; }
- }
- public virtual T SetChild<T> (T _child)
- {
- return base.SetChild (_child);
- }
-
- #region IXmlSerializable
-
- public override System.Xml.Schema.XmlSchema GetSchema()
- {
- return null;
- }
- 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
- subTree.Read(); //read first child
-
- if (!subTree.IsStartElement())
- return;
-
- Type t = Type.GetType("Crow." + subTree.Name);
- GraphicObject go = (GraphicObject)Activator.CreateInstance(t);
-
- (go as IXmlSerializable).ReadXml(subTree);
-
- SetChild(go);
-
- subTree.Read();//closing tag
- }
- }
- 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();
- }
-
- #endregion
- }
-}
-
+using System; +using System.Xml.Serialization; +using System.Reflection; +using OpenTK.Input; +using System.ComponentModel; +using System.Linq; + +namespace Crow +{ + public class Container : PrivateContainer, IXmlSerializable + { + #region CTOR + public Container() + : base() + { + } + public Container(Rectangle _bounds) + : base(_bounds) + { + } + #endregion + + [XmlIgnore] + public GraphicObject Child { + get { return child; } + set { child = value; } + } + public virtual T SetChild<T> (T _child) + { + return base.SetChild (_child); + } + + #region IXmlSerializable + + public override System.Xml.Schema.XmlSchema GetSchema() + { + return null; + } + 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 + subTree.Read(); //read first child + + if (!subTree.IsStartElement()) + return; + + Type t = Type.GetType("Crow." + subTree.Name); + GraphicObject go = (GraphicObject)Activator.CreateInstance(t); + + (go as IXmlSerializable).ReadXml(subTree); + + SetChild(go); + + subTree.Read();//closing tag + } + } + 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(); + } + + #endregion + } +} + diff --git a/src/GraphicObjects/Expandable.cs b/src/GraphicObjects/Expandable.cs index f1e2bdeb..f44e5e27 100644 --- a/src/GraphicObjects/Expandable.cs +++ b/src/GraphicObjects/Expandable.cs @@ -1,130 +1,130 @@ -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
-{
- [DefaultTemplate("#Crow.Templates.Expandable.goml")]
- public class Expandable : TemplatedContainer
- {
- bool _isExpanded;
- string caption;
- string image;
- Container _contentContainer;
-
- public event EventHandler Expand;
- public event EventHandler Collapse;
-
- public override GraphicObject Content {
- get {
- return _contentContainer == null ? null : _contentContainer.Child;
- }
- set {
- _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
- {
- get { return base.Focusable; }
- set { base.Focusable = value; }
- }
- [XmlAttributeAttribute()][DefaultValue(-1)]
- public override int Height {
- get { return base.Height; }
- set { base.Height = value; }
- }
-
- [XmlAttributeAttribute()][DefaultValue("Expandable")]
- public string Caption {
- get { return caption; }
- set {
- if (caption == value)
- return;
- caption = value;
- NotifyValueChanged ("Caption", caption);
- }
- }
- [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.expandable.svg")]
- public string Image {
- get { return image; }
- set {
- if (image == value)
- return;
- image = value;
- NotifyValueChanged ("Image", image);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(false)]
- public bool IsExpanded
- {
- get { return _isExpanded; }
- set
- {
- _isExpanded = value;
-
- if (_isExpanded) {
- onExpand (this, null);
- NotifyValueChanged ("SvgSub", "expanded");
- return;
- }
-
- onCollapse (this, null);
- NotifyValueChanged ("SvgSub", "collapsed");
- }
- }
-
- public virtual void onExpand(object sender, EventArgs e)
- {
- if (_contentContainer != null)
- _contentContainer.Visible = true;
-
- Expand.Raise (this, e);
- }
- public virtual void onCollapse(object sender, EventArgs e)
- {
- if (_contentContainer != null)
- _contentContainer.Visible = false;
-
- Collapse.Raise (this, e);
- }
-
- 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 ();
- }
- }
-}
+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 +{ + [DefaultTemplate("#Crow.Templates.Expandable.goml")] + public class Expandable : TemplatedContainer + { + bool _isExpanded; + string caption; + string image; + Container _contentContainer; + + public event EventHandler Expand; + public event EventHandler Collapse; + + public override GraphicObject Content { + get { + return _contentContainer == null ? null : _contentContainer.Child; + } + set { + _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 + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + [XmlAttributeAttribute()][DefaultValue(-1)] + public override int Height { + get { return base.Height; } + set { base.Height = value; } + } + + [XmlAttributeAttribute()][DefaultValue("Expandable")] + public string Caption { + get { return caption; } + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.expandable.svg")] + public string Image { + get { return image; } + set { + if (image == value) + return; + image = value; + NotifyValueChanged ("Image", image); + } + } + [XmlAttributeAttribute()][DefaultValue(false)] + public bool IsExpanded + { + get { return _isExpanded; } + set + { + _isExpanded = value; + + if (_isExpanded) { + onExpand (this, null); + NotifyValueChanged ("SvgSub", "expanded"); + return; + } + + onCollapse (this, null); + NotifyValueChanged ("SvgSub", "collapsed"); + } + } + + public virtual void onExpand(object sender, EventArgs e) + { + if (_contentContainer != null) + _contentContainer.Visible = true; + + Expand.Raise (this, e); + } + public virtual void onCollapse(object sender, EventArgs e) + { + if (_contentContainer != null) + _contentContainer.Visible = false; + + Collapse.Raise (this, e); + } + + 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 1624c530..53aff76b 100644 --- a/src/GraphicObjects/GenericStack.cs +++ b/src/GraphicObjects/GenericStack.cs @@ -1,178 +1,178 @@ -using System;
-using System.Diagnostics;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
- public class GenericStack : Group
- {
- internal class Page
- {
- public byte[] bmp;
- public int Size;
- }
-
- #region CTOR
- public GenericStack()
- : base()
- {
- }
- #endregion
-
- #region Private fields
- int _spacing;
- Orientation _orientation;
- #endregion
-
- public override T addChild<T> (T child)
- {
- T tmp = base.addChild (child);
- this.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- return tmp;
- }
- public override void removeChild (GraphicObject child)
- {
- base.removeChild (child);
- this.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- }
-
- #region Public Properties
- [XmlAttributeAttribute()][DefaultValue(2)]
- public int Spacing
- {
- get { return _spacing; }
- set {
- if (_spacing == value)
- return;
- _spacing = value;
- NotifyValueChanged ("Spacing", Spacing);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(Orientation.Horizontal)]
- public virtual Orientation Orientation
- {
- get { return _orientation; }
- set { _orientation = value; }
- }
- #endregion
-
- #region GraphicObject Overrides
- protected override Size measureRawSize ()
- {
- Size tmp = new Size ();
-
- if (Orientation == Orientation.Horizontal) {
- foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) {
- 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.Where(ch=>ch.Visible)) {
- tmp.Width = Math.Max (tmp.Width, Math.Max(c.Slot.Right, c.Slot.Width));
- tmp.Height += c.Slot.Height + Spacing;
- }
- if (tmp.Height > 0)
- tmp.Height -= Spacing;
- }
-
- tmp.Width += 2 * Margin;
- tmp.Height += 2 * Margin;
-
- return tmp;
- }
- 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.Where(ch=>ch.Visible)) {
- c.Slot.X = d;
- d += c.Slot.Width + Spacing;
- c.RegisterForLayouting ((int)LayoutingType.Y);
- }
- } else {
- foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) {
- c.Slot.Y = d;
- d += c.Slot.Height + Spacing;
- c.RegisterForLayouting ((int)LayoutingType.X);
- }
- }
- }
-
- public override void RegisterForLayouting (int layoutType)
- {
- if (Parent == null)
- return;
-
- base.RegisterForLayouting (layoutType);
-
- if ((layoutType & (int)LayoutingType.PositionChildren) > 0)
- Interface.LayoutingQueue.Enqueue (LayoutingType.PositionChildren, this);
-
- }
- public override void UpdateLayout (LayoutingType layoutType)
- {
- if (layoutType == LayoutingType.PositionChildren) {
- //allow 1 child to have size to 0 if stack has fixed or streched size,
- //this child will occupy remaining space
- if (Orientation == Orientation.Horizontal) {
- if (Width >= 0) {
- 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.Where(ch=>ch.Visible).Except (gobjs).Sum (g => g.Slot.Width);
- if (sz < Slot.Width) {
- gobjs [0].Slot.Width = Slot.Width - sz - (Children.Count-1) * Spacing - 2 * Margin;
- int idx = Children.IndexOf (gobjs [0]);
- if (idx > 0 && idx < Children.Count - 1)
- gobjs [0].Slot.Width -= Spacing;
- if (gobjs [0].LastSlots.Width != gobjs [0].Slot.Width) {
- gobjs [0].bmp = null;
- gobjs [0].OnLayoutChanges (LayoutingType.Width);
- gobjs [0].LastSlots.Width = gobjs [0].Slot.Width;
- }
- }
- }
- }
- } else {
- if (Height >= 0) {
- 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.Where(ch=>ch.Visible).Except (gobjs).Sum (g => g.Slot.Height);
- if (sz < Slot.Height) {
- gobjs [0].Slot.Height = Slot.Height - sz- (Children.Count-1) * Spacing - 2 * Margin;
- int idx = Children.IndexOf (gobjs [0]);
- if (idx > 0 && idx < Children.Count - 1)
- gobjs [0].Slot.Height -= Spacing;
- if (gobjs [0].LastSlots.Height != gobjs [0].Slot.Height) {
- gobjs [0].bmp = null;
- gobjs [0].OnLayoutChanges (LayoutingType.Height);
- gobjs [0].LastSlots.Height = gobjs [0].Slot.Height;
- }
- }
- }
- }
- }
- ComputeChildrenPositions ();
- //if no layouting remains in queue for item, registre for redraw
- if (Interface.LayoutingQueue.Where (lq => lq.GraphicObject == this).Count () <= 0 && bmp==null)
- this.RegisterForRedraw ();
- }else
- base.UpdateLayout(layoutType);
- }
- #endregion
-
-
- }
-}
+using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; +using System.ComponentModel; + +namespace Crow +{ + public class GenericStack : Group + { + internal class Page + { + public byte[] bmp; + public int Size; + } + + #region CTOR + public GenericStack() + : base() + { + } + #endregion + + #region Private fields + int _spacing; + Orientation _orientation; + #endregion + + public override T addChild<T> (T child) + { + T tmp = base.addChild (child); + this.RegisterForLayouting ((int)LayoutingType.PositionChildren); + return tmp; + } + public override void removeChild (GraphicObject child) + { + base.removeChild (child); + this.RegisterForLayouting ((int)LayoutingType.PositionChildren); + } + + #region Public Properties + [XmlAttributeAttribute()][DefaultValue(2)] + public int Spacing + { + get { return _spacing; } + set { + if (_spacing == value) + return; + _spacing = value; + NotifyValueChanged ("Spacing", Spacing); + } + } + [XmlAttributeAttribute()][DefaultValue(Orientation.Horizontal)] + public virtual Orientation Orientation + { + get { return _orientation; } + set { _orientation = value; } + } + #endregion + + #region GraphicObject Overrides + protected override Size measureRawSize () + { + Size tmp = new Size (); + + if (Orientation == Orientation.Horizontal) { + foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { + 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.Where(ch=>ch.Visible)) { + tmp.Width = Math.Max (tmp.Width, Math.Max(c.Slot.Right, c.Slot.Width)); + tmp.Height += c.Slot.Height + Spacing; + } + if (tmp.Height > 0) + tmp.Height -= Spacing; + } + + tmp.Width += 2 * Margin; + tmp.Height += 2 * Margin; + + return tmp; + } + 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.Where(ch=>ch.Visible)) { + c.Slot.X = d; + d += c.Slot.Width + Spacing; + c.RegisterForLayouting ((int)LayoutingType.Y); + } + } else { + foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { + c.Slot.Y = d; + d += c.Slot.Height + Spacing; + c.RegisterForLayouting ((int)LayoutingType.X); + } + } + } + + public override void RegisterForLayouting (int layoutType) + { + if (Parent == null) + return; + + base.RegisterForLayouting (layoutType); + + if ((layoutType & (int)LayoutingType.PositionChildren) > 0) + Interface.LayoutingQueue.Enqueue (LayoutingType.PositionChildren, this); + + } + public override void UpdateLayout (LayoutingType layoutType) + { + if (layoutType == LayoutingType.PositionChildren) { + //allow 1 child to have size to 0 if stack has fixed or streched size, + //this child will occupy remaining space + if (Orientation == Orientation.Horizontal) { + if (Width >= 0) { + 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.Where(ch=>ch.Visible).Except (gobjs).Sum (g => g.Slot.Width); + if (sz < Slot.Width) { + gobjs [0].Slot.Width = Slot.Width - sz - (Children.Count-1) * Spacing - 2 * Margin; + int idx = Children.IndexOf (gobjs [0]); + if (idx > 0 && idx < Children.Count - 1) + gobjs [0].Slot.Width -= Spacing; + if (gobjs [0].LastSlots.Width != gobjs [0].Slot.Width) { + gobjs [0].bmp = null; + gobjs [0].OnLayoutChanges (LayoutingType.Width); + gobjs [0].LastSlots.Width = gobjs [0].Slot.Width; + } + } + } + } + } else { + if (Height >= 0) { + 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.Where(ch=>ch.Visible).Except (gobjs).Sum (g => g.Slot.Height); + if (sz < Slot.Height) { + gobjs [0].Slot.Height = Slot.Height - sz- (Children.Count-1) * Spacing - 2 * Margin; + int idx = Children.IndexOf (gobjs [0]); + if (idx > 0 && idx < Children.Count - 1) + gobjs [0].Slot.Height -= Spacing; + if (gobjs [0].LastSlots.Height != gobjs [0].Slot.Height) { + gobjs [0].bmp = null; + gobjs [0].OnLayoutChanges (LayoutingType.Height); + gobjs [0].LastSlots.Height = gobjs [0].Slot.Height; + } + } + } + } + } + ComputeChildrenPositions (); + //if no layouting remains in queue for item, registre for redraw + if (Interface.LayoutingQueue.Where (lq => lq.GraphicObject == this).Count () <= 0 && bmp==null) + this.RegisterForRedraw (); + }else + base.UpdateLayout(layoutType); + } + #endregion + + + } +} diff --git a/src/GraphicObjects/GraduatedSlider.cs b/src/GraphicObjects/GraduatedSlider.cs index 9ed5e19e..3d916a8c 100644 --- a/src/GraphicObjects/GraduatedSlider.cs +++ b/src/GraphicObjects/GraduatedSlider.cs @@ -1,54 +1,54 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Cairo;
-using System.Xml.Serialization;
-
-namespace Crow
-{
- public class GraduatedSlider : Slider
- {
- #region CTOR
- public GraduatedSlider() : base()
- {}
- public GraduatedSlider(double minimum, double maximum, double step)
- : base()
- {
- Minimum = minimum;
- Maximum = maximum;
- SmallIncrement = step;
- LargeIncrement = step * 5;
- }
- #endregion
-
- protected override void DrawGraduations(Context gr, PointD pStart, PointD pEnd)
- {
- Rectangle r = ClientRectangle;
- gr.SetSourceColor(Foreground);
-
- gr.LineWidth = 2;
- gr.MoveTo(pStart);
- gr.LineTo(pEnd);
-
- gr.Stroke();
- gr.LineWidth = 1;
-
- double sst = unity * SmallIncrement;
- double bst = unity * LargeIncrement;
-
-
- PointD vBar = new PointD(0, sst);
- for (double x = Minimum; x <= Maximum - Minimum; x += SmallIncrement)
- {
- double lineLength = r.Height / 3;
- if (x % LargeIncrement != 0)
- lineLength /= 3;
- PointD p = new PointD(pStart.X + x * unity, pStart.Y);
- gr.MoveTo(p);
- gr.LineTo(new PointD(p.X, p.Y + lineLength));
- }
- gr.Stroke();
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Cairo; +using System.Xml.Serialization; + +namespace Crow +{ + public class GraduatedSlider : Slider + { + #region CTOR + public GraduatedSlider() : base() + {} + public GraduatedSlider(double minimum, double maximum, double step) + : base() + { + Minimum = minimum; + Maximum = maximum; + SmallIncrement = step; + LargeIncrement = step * 5; + } + #endregion + + protected override void DrawGraduations(Context gr, PointD pStart, PointD pEnd) + { + Rectangle r = ClientRectangle; + gr.SetSourceColor(Foreground); + + gr.LineWidth = 2; + gr.MoveTo(pStart); + gr.LineTo(pEnd); + + gr.Stroke(); + gr.LineWidth = 1; + + double sst = unity * SmallIncrement; + double bst = unity * LargeIncrement; + + + PointD vBar = new PointD(0, sst); + for (double x = Minimum; x <= Maximum - Minimum; x += SmallIncrement) + { + double lineLength = r.Height / 3; + if (x % LargeIncrement != 0) + lineLength /= 3; + PointD p = new PointD(pStart.X + x * unity, pStart.Y); + gr.MoveTo(p); + gr.LineTo(new PointD(p.X, p.Y + lineLength)); + } + gr.Stroke(); + } + } +} diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index cef2c501..5613c0c9 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -1,1381 +1,1381 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-//using OpenTK.Graphics.OpenGL;
-using System.Drawing.Imaging;
-using System.Diagnostics;
-using OpenTK.Input;
-
-using Cairo;
-
-using System.Xml.Serialization;
-using System.Reflection;
-using System.ComponentModel;
-using System.IO;
-//using System.Xml;
-using System.Xml;
-using System.Runtime.CompilerServices;
-using System.Reflection.Emit;
-
-namespace Crow
-{
- public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange
- {
- #if DEBUG_LAYOUTING
- internal static ulong currentUid = 0;
- internal ulong uid = 0;
- #endif
-
- internal List<Binding> Bindings = new List<Binding> ();
-
- #region IValueChange implementation
- public event EventHandler<ValueChangeEventArgs> ValueChanged;
- public virtual void NotifyValueChanged(string MemberName, object _value)
- {
- ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value));
- }
- #endregion
-
- #region CTOR
- public GraphicObject ()
- {
- #if DEBUG_LAYOUTING
- uid = currentUid;
- currentUid++;
- #endif
-
- if (Interface.XmlSerializerInit)
- return;
-
- loadDefaultValues ();
- registerForGraphicUpdate ();
- }
- public GraphicObject (Rectangle _bounds)
- {
- if (Interface.XmlSerializerInit)
- return;
-
- loadDefaultValues ();
- Bounds = _bounds;
- registerForGraphicUpdate ();
- }
- #endregion
-
- #region private fields
- ILayoutable _parent;
- string _name = "unamed";
- Color _background = Color.Transparent;
- Color _foreground = Color.White;
- Font _font = "droid, 10";
- double _cornerRadius = 0;
- int _margin = 0;
- bool _focusable = false;
- bool _hasFocus = false;
- bool _mouseRepeat;
- protected bool _isVisible = true;
- VerticalAlignment _verticalAlignment = VerticalAlignment.Center;
- HorizontalAlignment _horizontalAlignment = HorizontalAlignment.Center;
- Size _maximumSize = "0;0";
- Size _minimumSize = "0;0";
-
- Picture _backgroundImage;
- string _backgroundImagePath;
- #endregion
-
- #region public fields
- public GraphicObject LogicalParent;
- public Rectangle Bounds;
- public Rectangle Slot = new Rectangle ();
- public object Tag;
- public byte[] bmp;
- #endregion
-
- #region ILayoutable
- //TODO: it would save the recurent cost of a cast in event bubbling if parent type was GraphicObject
- // or we could add to the interface the mouse events
- [XmlIgnore]public ILayoutable Parent {
- get { return _parent; }
- set {
-// if (_parent == value)
-// return;
-// if (_parent != null)
-// ClearBinding ();
-//
- _parent = value;
-//
-// if (DataSource != null)
-// ResolveBindings ();
- }
- }
-
-
- [XmlIgnore]public virtual Rectangle ClientRectangle {
- get {
- Rectangle cb = Slot.Size;
- cb.Inflate ( - Margin);
- return cb;
- }
- }
- [XmlIgnore]public virtual IGOLibHost HostContainer {
- get { return Parent == null ? null : Parent.HostContainer; }
- }
- public virtual Rectangle ContextCoordinates(Rectangle r){
- return
- Parent.ContextCoordinates (r);// + ClientRectangle.Position;
- }
- public virtual Rectangle ScreenCoordinates (Rectangle r){
- //r += Slot.Position;
-
- return
- Parent.ScreenCoordinates(r) + Parent.getSlot().Position + Parent.ClientRectangle.Position;
- }
- public virtual Rectangle getSlot()
- {
- return Slot;
- }
- public virtual Rectangle getBounds()
- {
- return Bounds;
- }
- #endregion
-
- #region EVENT HANDLERS
- public event EventHandler<MouseWheelEventArgs> MouseWheelChanged;
- public event EventHandler<MouseButtonEventArgs> MouseUp;
- public event EventHandler<MouseButtonEventArgs> MouseDown;
- public event EventHandler<MouseButtonEventArgs> MouseClick;
- public event EventHandler<MouseMoveEventArgs> MouseMove;
- public event EventHandler<MouseMoveEventArgs> MouseEnter;
- public event EventHandler<MouseMoveEventArgs> MouseLeave;
- public event EventHandler<KeyboardKeyEventArgs> KeyDown;
- public event EventHandler<KeyboardKeyEventArgs> KeyUp;
- public event EventHandler Focused;
- public event EventHandler Unfocused;
- public event EventHandler<LayoutChangeEventArgs> LayoutChanged;
- #endregion
-
- #region public properties
- [XmlAttributeAttribute()][DefaultValue("unamed")]
- public virtual string Name {
- get { return _name; }
- set {
- if (_name == value)
- return;
- _name = value;
- NotifyValueChanged("Name", _verticalAlignment);
- }
- }
- [XmlAttributeAttribute ()][DefaultValue(VerticalAlignment.Center)]
- public virtual VerticalAlignment VerticalAlignment {
- get { return _verticalAlignment; }
- set {
- if (_verticalAlignment == value)
- return;
-
- _verticalAlignment = value;
- NotifyValueChanged("VerticalAlignment", _verticalAlignment);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(HorizontalAlignment.Center)]
- public virtual HorizontalAlignment HorizontalAlignment {
- get { return _horizontalAlignment; }
- set {
- if (_horizontalAlignment == value)
- return;
-
- _horizontalAlignment = value;
- NotifyValueChanged("HorizontalAlignment", _horizontalAlignment);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(0)]
- public virtual int Left {
- get { return Bounds.X; }
- set {
- if (Bounds.X == value)
- return;
-
- Bounds.X = value;
- NotifyValueChanged ("Left", Bounds.X);
- this.RegisterForLayouting ((int)LayoutingType.X);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(0)]
- public virtual int Top {
- get { return Bounds.Y; }
- set {
- if (Bounds.Y == value)
- return;
-
- Bounds.Y = value;
- NotifyValueChanged ("Top", Bounds.Y);
- this.RegisterForLayouting ((int)LayoutingType.Y);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(0)]
- public virtual int Width {
- get { return Bounds.Width; }
- set {
- if (Bounds.Width == value)
- return;
-
- Bounds.Width = value;
- NotifyValueChanged ("Width", Bounds.Width);
- this.RegisterForLayouting ((int)LayoutingType.Width);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(0)]
- public virtual int Height {
- get { return Bounds.Height; }
- set {
- if (Bounds.Height == value)
- return;
-
- Bounds.Height = value;
- NotifyValueChanged ("Height", Bounds.Height);
- this.RegisterForLayouting ((int)LayoutingType.Height);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(false)]
- public virtual bool Fit {
- get { return Bounds.Width < 0 && Bounds.Height < 0 ? true : false; }
- set {
- if (value == Fit)
- return;
-
- Bounds.Width = Bounds.Height = -1;
- }
- }
- [XmlAttributeAttribute()][DefaultValue(false)]
- public virtual bool Focusable {
- get { return _focusable; }
- set {
- if (_focusable == value)
- return;
- _focusable = value;
- NotifyValueChanged ("Focusable", _focusable);
- }
- }
- [XmlIgnore]public virtual bool HasFocus {
- get { return _hasFocus; }
- set {
- if (value == _hasFocus)
- return;
-
- _hasFocus = value;
- NotifyValueChanged ("HasFocus", _hasFocus);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(false)]
- public virtual bool MouseRepeat {
- get { return _mouseRepeat; }
- set {
- if (_mouseRepeat == value)
- return;
- _mouseRepeat = value;
- NotifyValueChanged ("MouseRepeat", _mouseRepeat);
- }
- }
- [XmlAttributeAttribute()][DefaultValue("Transparent")]
- public virtual Color Background {
- get { return _background; }
- set {
- if (_background == value)
- return;
- _background = value;
- NotifyValueChanged ("Background", _background);
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue("White")]
- public virtual Color Foreground {
- get { return _foreground; }
- set {
- if (_foreground == value)
- return;
- _foreground = value;
- NotifyValueChanged ("Foreground", _foreground);
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue("droid,10")]
- public virtual Font Font {
- get { return _font; }
- set {
- if (value == _font)
- return;
- _font = value;
- NotifyValueChanged ("Font", _font);
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(0.0)]
- public virtual double CornerRadius {
- get { return _cornerRadius; }
- set {
- if (value == _cornerRadius)
- return;
- _cornerRadius = value;
- NotifyValueChanged ("CornerRadius", _cornerRadius);
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(0)]
- public virtual int Margin {
- get { return _margin; }
- set {
- if (value == _margin)
- return;
- _margin = value;
- NotifyValueChanged ("Margin", _margin);
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(true)]
- public virtual bool Visible {
- get { return _isVisible; }
- set {
- if (value == _isVisible)
- return;
-
- _isVisible = value;
-
- if (HostContainer == null)
- return;
- //add slot to clipping to redraw
- HostContainer.gobjsToRedraw.Add (this);
-
- //ensure main win doesn't keep hidden childrens ref
- if (this.Contains (HostContainer.hoverWidget))
- HostContainer.hoverWidget = null;
- if (Parent is GenericStack)
- Parent.RegisterForLayouting ((int)LayoutingType.Sizing | (int)LayoutingType.PositionChildren);
-
- NotifyValueChanged ("Visible", _isVisible);
- }
- }
- //TODO: only used in group, should be removed from base go object
- [XmlIgnore]public virtual bool DrawingIsValid
- { get { return bmp == null ?
- false :
- true; } }
- [XmlAttributeAttribute()][DefaultValue("0;0")]
- public virtual Size MaximumSize {
- get { return _maximumSize; }
- set { _maximumSize = value; }
- }
- [XmlAttributeAttribute()][DefaultValue("0;0")]
- public virtual Size MinimumSize {
- get { return _minimumSize; }
- set { _minimumSize = value; }
- }
- object dataSource;
-
- [XmlIgnore]public virtual object DataSource {
- set {
- if (dataSource == value)
- return;
-
- if (dataSource != null)
- this.ClearBinding ();
-
- dataSource = value;
-
- if (dataSource != null)
- this.ResolveBindings();
- }
- get {
- return dataSource == null ?
- LogicalParent == null ?
- Parent is GraphicObject ? (Parent as GraphicObject).DataSource : null : LogicalParent.DataSource : dataSource;
- }
- }
- #endregion
-
-
- /// <summary>
- /// Loads the default values from XML attributes default
- /// </summary>
- protected virtual void loadDefaultValues()
- {
- foreach (PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
- if (pi.GetSetMethod () == null)
- continue;
- string name = "";
-
- object[] att = pi.GetCustomAttributes (false);
-
- foreach (object o in att) {
- XmlAttributeAttribute xaa = o as XmlAttributeAttribute;
- if (xaa != null) {
- if (string.IsNullOrEmpty (xaa.AttributeName))
- name = pi.Name;
- else
- name = xaa.AttributeName;
- continue;
- }
-
- XmlIgnoreAttribute xia = o as XmlIgnoreAttribute;
- if (xia != null)
- continue;
-
- DefaultValueAttribute dv = o as DefaultValueAttribute;
- if (dv != null) {
- object defaultValue = dv.Value;
- //avoid system types automaticaly converted by parser
- if (defaultValue != null && !pi.PropertyType.Namespace.StartsWith("System")) {
- if (pi.PropertyType != defaultValue.GetType()) {
- MethodInfo miParse = pi.PropertyType.GetMethod ("Parse", BindingFlags.Static | BindingFlags.Public);
- if (miParse != null) {
- pi.SetValue (this, miParse.Invoke (null, new object[]{ defaultValue }), null);
- continue;
- }
- }
- }
- pi.SetValue (this, defaultValue, null);
- }
- }
- }
- }
-
- public virtual GraphicObject FindByName(string nameToFind){
- return nameToFind == _name ? this : null;
- }
- public virtual bool Contains(GraphicObject goToFind){
- return false;
- }
-
-
- /// <summary>
- /// Clear chached object and add clipping region in redraw list of interface
- /// </summary>
- public virtual void registerForGraphicUpdate ()
- {
- bmp = null;
- if (HostContainer != null)
- HostContainer.gobjsToRedraw.Add (this);
- }
- /// <summary>
- /// Add clipping region in redraw list of interface, dont update cached object content
- /// </summary>
- public virtual void RegisterForRedraw ()
- {
- if (HostContainer != null)
- HostContainer.gobjsToRedraw.Add (this);
- }
-
- /// <summary>
- /// keep last slot components for each layouting pass to track
- /// changes and trigger update of other component accordingly
- /// </summary>
- public Rectangle LastSlots;
- /// <summary>
- /// keep last slot painted on screen to clear traces if moved or resized
- /// TODO: we should ensure the whole parsed widget tree is the last painted
- /// version to clear effective oldslot if parents have been moved or resized.
- /// IDEA is to add a ScreenCoordinates function that use only lastPaintedSlots
- /// </summary>
- public Rectangle LastPaintedSlot;
-
- public virtual void registerClipRect()
- {
- HostContainer.redrawClip.AddRectangle (ScreenCoordinates(Slot));
- //this clipping should take only last painted slots in ancestor tree which
- //is not the case for now.
- HostContainer.redrawClip.AddRectangle (ScreenCoordinates(LastPaintedSlot));
- }
- /// <summary> return size of content + margins </summary>
- protected virtual Size measureRawSize ()
- {
- return Bounds.Size;
- }
- /// <summary> clear current layoutingQueue items for object and
- /// trigger a new layouting pass for a layoutType </summary>
- public virtual void RegisterForLayouting(int layoutType)
- {
- if (Parent == null)
- return;
- #if DEBUG_LAYOUTING
- Debug.WriteLine ("RegisterForLayouting => {1}->{0}", layoutType, this.ToString());
- #endif
- lock (Interface.LayoutingQueue) {
- 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 if (Bounds.Width < 0) //fit
- Interface.LayoutingQueue.EnqueueBeforeParentSizing (LayoutingType.Width, this);
- else
- Interface.LayoutingQueue.Insert (0, new LayoutingQueueItem (LayoutingType.Width, this));
- }
-
- if ((layoutType & (int)LayoutingType.Height) > 0) {
- if (Bounds.Height == 0) //stretch in parent
- Interface.LayoutingQueue.EnqueueAfterParentSizing (LayoutingType.Height, this);
- else if (Bounds.Height < 0) //fit
- Interface.LayoutingQueue.EnqueueBeforeParentSizing (LayoutingType.Height, this);
- else
- Interface.LayoutingQueue.Insert (0, new LayoutingQueueItem (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);
- }
- }
-
- /// <summary> trigger dependant sizing component update </summary>
- public virtual void OnLayoutChanges(LayoutingType layoutType)
- {
- if (Parent==null)
- return;
- #if DEBUG_LAYOUTING
- Debug.WriteLine ("Layout change: " + this.ToString () + ":" + LastSlots.ToString() + "=>" + Slot.ToString ());
- #endif
-
- switch (layoutType) {
- case LayoutingType.Width:
- if (Parent.getBounds ().Width < 0) {
- Group gw = Parent as Group;
- if (gw != null) {
- if (Slot.Width > gw.maxChildrenWidth)
- gw.maxChildrenWidth = Slot.Width;
- }
- this.Parent.RegisterForLayouting ((int)LayoutingType.Width);
- }else if (Width != 0) //update position in parent
- this.RegisterForLayouting ((int)LayoutingType.X);
- GenericStack gsw = Parent as GenericStack;
- if (gsw == null)
- break;
- if ((Parent as GenericStack).Orientation == Orientation.Horizontal) {
-// ulong idx = (ulong)gsw.Children.IndexOf (this);
-// if (idx < gsw.stackingUpdateStartIndex)
-// gsw.stackingUpdateStartIndex = idx;
- this.Parent.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- }
- break;
- case LayoutingType.Height:
- if (Parent.getBounds ().Height < 0) {
- Group gh = Parent as Group;
- if (gh != null) {
- if (Slot.Width > gh.maxChildrenHeight)
- gh.maxChildrenHeight = Slot.Height;
- }
- this.Parent.RegisterForLayouting ((int)LayoutingType.Height);
- }else if (Height != 0) //update position in parent
- this.RegisterForLayouting ((int)LayoutingType.Y);
- GenericStack gsh = Parent as GenericStack;
- if (gsh==null)
- break;
- if (gsh.Orientation == Orientation.Vertical) {
-// ulong idx = (ulong)gsh.Children.IndexOf (this);
-// if (idx < gsh.stackingUpdateStartIndex)
-// gsh.stackingUpdateStartIndex = idx;
- this.Parent.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- }
- break;
- }
- LayoutChanged.Raise (this, new LayoutChangeEventArgs (layoutType));
- }
- /// <summary> Update layout component, this is where the computation of alignement
- /// and size take place </summary>
- public virtual void UpdateLayout (LayoutingType layoutType)
- {
- switch (layoutType) {
- case LayoutingType.X:
- if (Bounds.X == 0) {
- switch (HorizontalAlignment) {
- case HorizontalAlignment.Left:
- Slot.X = 0;
- break;
- case HorizontalAlignment.Right:
- Slot.X = Parent.ClientRectangle.Width - Slot.Width;
- break;
- case HorizontalAlignment.Center:
- Slot.X = Parent.ClientRectangle.Width / 2 - Slot.Width / 2;
- break;
- }
- } else
- Slot.X = Bounds.X;
-
- if (LastSlots.X == Slot.X)
- break;
-
- bmp = null;
-
- OnLayoutChanges (layoutType);
-
- LastSlots.X = Slot.X;
- break;
- case LayoutingType.Y:
- if (Bounds.Y == 0) {
- switch (VerticalAlignment) {
- case VerticalAlignment.Top:
- Slot.Y = 0;
- break;
- case VerticalAlignment.Bottom:
- Slot.Y = Parent.ClientRectangle.Height - Slot.Height;
- break;
- case VerticalAlignment.Center:
- Slot.Y = Parent.ClientRectangle.Height / 2 - Slot.Height / 2;
- break;
- }
- }else
- Slot.Y = Bounds.Y;
-
- if (LastSlots.Y == Slot.Y)
- break;
-
- bmp = null;
-
- OnLayoutChanges (layoutType);
-
- 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
- Slot.Width = Parent.ClientRectangle.Width;
-
- //size constrain
- if (Slot.Width < MinimumSize.Width)
- Slot.Width = MinimumSize.Width;
- else if (Slot.Width > MaximumSize.Width && MaximumSize.Width > 0)
- Slot.Width = MaximumSize.Width;
-
- if (LastSlots.Width == Slot.Width)
- break;
-
- bmp = null;
-
- OnLayoutChanges (layoutType);
-
- 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
- Slot.Height = Parent.ClientRectangle.Height;
-
- //size constrain
- if (Slot.Height < MinimumSize.Height)
- Slot.Height = MinimumSize.Height;
- else if (Slot.Height > MaximumSize.Height && MaximumSize.Height > 0)
- Slot.Height = MaximumSize.Height;
-
-
- if (LastSlots.Height == Slot.Height)
- break;
-
- bmp = null;
-
- OnLayoutChanges (layoutType);
-
- LastSlots.Height = Slot.Height;
- break;
- }
- lock (Interface.LayoutingQueue) {
- //if no layouting remains in queue for item, registre for redraw
- if (Interface.LayoutingQueue.Where (lq => lq.GraphicObject == this).Count () <= 0 && bmp == null)
- this.RegisterForRedraw ();
- }
- }
-
- /// <summary> This is the common overridable drawing routine to create new widget </summary>
- protected virtual void onDraw(Context gr)
- {
- Rectangle rBack = new Rectangle (Slot.Size);
-
- Background.SetAsSource (gr);
- CairoHelpers.CairoRectangle(gr,rBack,_cornerRadius);
- gr.Fill ();
- }
-
- /// <summary>
- /// Interfal drawing context creation on a cached surface limited to slot size
- /// this trigger the effective drawing routine </summary>
- protected virtual void UpdateGraphic ()
- {
- LastPaintedSlot = Slot;
-
- int stride = 4 * Slot.Width;
-
- int bmpSize = Math.Abs (stride) * Slot.Height;
- bmp = new byte[bmpSize];
-
- using (ImageSurface draw =
- new ImageSurface(bmp, Format.Argb32, Slot.Width, Slot.Height, stride)) {
- using (Context gr = new Context (draw)) {
- gr.Antialias = Antialias.Subpixel;
- onDraw (gr);
- }
- draw.Flush ();
- //draw.WriteToPng ("/mnt/data/test.png");
- }
- }
- /// <summary> Chained painting routine on the parent context of the actual cached version
- /// of the widget </summary>
- public virtual void Paint (ref Context ctx, Rectangles clip = null)
- {
- if (!Visible)
- return;
-
- if (bmp == null)
- UpdateGraphic ();
-
- Rectangle rb = Parent.ContextCoordinates(Slot);
-
- using (ImageSurface source = new ImageSurface(bmp, Format.Argb32, Slot.Width, Slot.Height, 4 * Slot.Width)) {
- if (this.Background == Color.Clear) {
- ctx.Save ();
- ctx.Operator = Operator.Clear;
- ctx.Rectangle(rb);
- ctx.Fill ();
- ctx.Restore ();
- }
- ctx.SetSourceSurface (source, rb.X, rb.Y);
- ctx.Paint ();
- }
- }
-
- #region Keyboard handling
- public virtual void onKeyDown(object sender, KeyboardKeyEventArgs e){
- KeyDown.Raise (sender, e);
- }
- #endregion
-
- #region Mouse handling
- public virtual bool MouseIsIn(Point m)
- {
- if (!Visible)
- return false;
- if (ScreenCoordinates (Slot).ContainsOrIsEqual (m)) {
- Scroller scr = Parent as Scroller;
- if (scr == null)
- return true;
- return scr.MouseIsIn (scr.savedMousePos);
- }
- return false;
- }
- public virtual void checkHoverWidget(MouseMoveEventArgs e)
- {
- IGOLibHost glh = HostContainer;
- if (glh.hoverWidget != this) {
- glh.hoverWidget = this;
- onMouseEnter (this, e);
- }
-
- this.onMouseMove (this, e);
- }
- public virtual void onMouseMove(object sender, MouseMoveEventArgs e)
- {
- //bubble event to the top
- GraphicObject p = Parent as GraphicObject;
- if (p != null)
- p.onMouseMove(sender,e);
-
- MouseMove.Raise (sender, e);
- }
- public virtual void onMouseDown(object sender, MouseButtonEventArgs e){
- IGOLibHost hc = HostContainer;
- if (hc.activeWidget == null)
- hc.activeWidget = this;
- if (this.Focusable && !Interface.FocusOnHover) {
- BubblingMouseButtonEventArg be = e as BubblingMouseButtonEventArg;
- if (be.Focused == null) {
- be.Focused = this;
- hc.FocusedWidget = this;
- }
- }
- //bubble event to the top
- GraphicObject p = Parent as GraphicObject;
- if (p != null)
- p.onMouseDown(sender,e);
-
- MouseDown.Raise (this, e);
- }
- public virtual void onMouseUp(object sender, MouseButtonEventArgs e){
- //bubble event to the top
- GraphicObject p = Parent as GraphicObject;
- if (p != null)
- p.onMouseUp(sender,e);
-
- MouseUp.Raise (this, e);
-
- if (MouseIsIn (e.Position)&&HasFocus)
- onMouseClick(sender,e);
- }
- public virtual void onMouseClick(object sender, MouseButtonEventArgs e){
- MouseClick.Raise (this, e);
- }
- public virtual void onMouseWheel(object sender, MouseWheelEventArgs e){
- GraphicObject p = Parent as GraphicObject;
- if (p != null)
- p.onMouseWheel(this,e);
-
- MouseWheelChanged.Raise (this, e);
- }
- public virtual void onFocused(object sender, EventArgs e){
- Focused.Raise (this, e);
- this.HasFocus = true;
- }
- public virtual void onUnfocused(object sender, EventArgs e){
- Unfocused.Raise (this, e);
- this.HasFocus = false;
- }
- public virtual void onMouseEnter(object sender, MouseMoveEventArgs e)
- {
- MouseEnter.Raise (this, e);
- }
- public virtual void onMouseLeave(object sender, MouseMoveEventArgs e)
- {
- MouseLeave.Raise (this, e);
- }
- #endregion
-
- public override string ToString ()
- {
- string tmp ="";
-
- if (Parent != null)
- tmp = Parent.ToString () + tmp;
- #if DEBUG_LAYOUTING
- return Name == "unamed" ? tmp + "." + this.GetType ().Name + uid.ToString(): tmp + "." + Name;
- #else
- return Name == "unamed" ? tmp + "." + this.GetType ().Name : tmp + "." + Name;
- #endif
- }
-
- #region Binding
- public virtual void ResolveBindings()
- {
- #if DEBUG_BINDING
- Debug.WriteLine ("ResolveBinding => " + this.ToString ());
- #endif
- List<Binding> resolved = new List<Binding> ();
- foreach (Binding b in Bindings) {
- if (!string.IsNullOrEmpty (b.DynMethodId))
- continue;
- if (b.Source.Member.MemberType == MemberTypes.Event) {
- if (b.Expression.StartsWith("{")){
- CompileEventSource(b);
- continue;
- }
- }
- if (!b.FindTarget ())
- 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);
- continue;
- }
-
- MethodInfo addHandler = b.Source.Event.GetAddMethod ();
- Delegate del = Delegate.CreateDelegate (b.Source.Event.EventHandlerType, b.Target.Instance, b.Target.Method);
- addHandler.Invoke (this, new object[] { del });
- continue;
- }
- resolved.Add (b);
- }
- //group;only one dynMethods by target (valuechanged event source)
- //changed value name tested in switch
- IEnumerable<Binding[]> groupedByTarget = resolved.GroupBy (g => g.Target.Instance, g => g, (k, g) => g.ToArray ());
- foreach (Binding[] grouped in groupedByTarget) {
- int i = 0;
- Type targetType = grouped[0].Target.Instance.GetType();
- Type sourceType = this.GetType();
-
- DynamicMethod dm = null;
- ILGenerator il = null;
-
- MethodInfo stringEquals = typeof(string).GetMethod
- ("op_Equality", new Type[2] {typeof(string), typeof(string)});
-
-
- System.Reflection.Emit.Label[] jumpTable = null;
- System.Reflection.Emit.Label endMethod = new System.Reflection.Emit.Label();
-
- #region Retrieve EventHandler parameter type
- EventInfo ei = targetType.GetEvent ("ValueChanged");
- //no dynamic update if ValueChanged interface is not implemented
- if (ei != null){
- MethodInfo evtInvoke = ei.EventHandlerType.GetMethod ("Invoke");
- ParameterInfo[] evtParams = evtInvoke.GetParameters ();
- Type handlerArgsType = evtParams [1].ParameterType;
-
- Type[] args = {typeof(object), typeof(object),handlerArgsType};
- dm = new DynamicMethod(grouped[0].NewDynMethodId,
- MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot,
- CallingConventions.Standard,
- typeof(void),
- args,
- sourceType,true);
-
- il = dm.GetILGenerator(256);
-
- endMethod = il.DefineLabel();
- jumpTable = new System.Reflection.Emit.Label[grouped.Length];
- for (i = 0; i < grouped.Length; i++)
- jumpTable [i] = il.DefineLabel ();
- il.DeclareLocal(typeof(string));
- il.DeclareLocal(typeof(object));
-
- il.Emit(OpCodes.Nop);
- il.Emit(OpCodes.Ldarg_0);
- //il.Emit(OpCodes.Isinst, sourceType);
- //push new value onto stack
- il.Emit(OpCodes.Ldarg_2);
- FieldInfo fiNewValue = typeof(ValueChangeEventArgs).GetField("NewValue");
- il.Emit(OpCodes.Ldfld, fiNewValue);
- il.Emit(OpCodes.Stloc_1);
- //push name
- il.Emit(OpCodes.Ldarg_2);
- FieldInfo fiMbName = typeof(ValueChangeEventArgs).GetField("MemberName");
- il.Emit(OpCodes.Ldfld, fiMbName);
- il.Emit(OpCodes.Stloc_0);
- il.Emit(OpCodes.Ldloc_0);
- il.Emit(OpCodes.Brfalse, endMethod);
- }
- #endregion
-
- i = 0;
- foreach (Binding b in grouped) {
- #region initialize target with actual value
- object targetValue = null;
- if (b.Target.Member != null){
- if (b.Target.Member.MemberType == MemberTypes.Property)
- targetValue = b.Target.Property.GetGetMethod ().Invoke (b.Target.Instance, null);
- else if (b.Target.Member.MemberType == MemberTypes.Field)
- targetValue = b.Target.Field.GetValue (b.Target.Instance);
- else if (b.Target.Member.MemberType == MemberTypes.Method){
- MethodInfo mthSrc = b.Target.Method;
- if (mthSrc.IsDefined(typeof(ExtensionAttribute), false))
- targetValue = mthSrc.Invoke(null, new object[] {b.Target.Instance});
- else
- targetValue = mthSrc.Invoke(b.Target.Instance, null);
- }else
- throw new Exception ("unandled source member type for binding");
- }else if (string.IsNullOrEmpty(b.Expression))
- targetValue= grouped [0].Target.Instance;//empty binding exp=> bound to target object by default
- //TODO: handle other dest type conversions
- if (b.Source.Property.PropertyType == typeof(string)){
- if (targetValue == null){
- //set default value
-
- }else
- targetValue = targetValue.ToString ();
- }
- b.Source.Property.GetSetMethod ().Invoke (this, new object[] { targetValue });
- #endregion
-
- //if no dyn update, skip jump table
- if (il == null)
- continue;
-
- il.Emit (OpCodes.Ldloc_0);
- if (b.Target.Member != null)
- il.Emit (OpCodes.Ldstr, b.Target.Member.Name);
- else
- il.Emit (OpCodes.Ldstr, b.Expression.Split('/').LastOrDefault());
- il.Emit (OpCodes.Callvirt, stringEquals);
- il.Emit (OpCodes.Brtrue, jumpTable[i]);
- i++;
- }
-
- if (il == null)
- continue;
-
- il.Emit (OpCodes.Br, endMethod);
-
- i = 0;
- foreach (Binding b in grouped) {
-
- il.MarkLabel (jumpTable [i]);
- il.Emit(OpCodes.Ldloc_1);
-
- //by default, target value type is deducted from source member type to allow
- //memberless binding, if targetMember exists, it will be used to determine target
- //value type for conversion
- Type targetValueType = b.Source.Property.PropertyType;
- if (b.Target.Member != null) {
- if (b.Target.Member.MemberType == MemberTypes.Property)
- targetValueType = b.Target.Property.PropertyType;
- else if (b.Target.Member.MemberType == MemberTypes.Field)
- targetValueType = b.Target.Field.FieldType;
- else
- throw new Exception ("unhandle target member type in binding");
- }
-
- if (!targetValueType.IsValueType)
- il.Emit(OpCodes.Castclass, targetValueType);
- else if (b.Source.Property.PropertyType != targetValueType)
- il.Emit(OpCodes.Callvirt, CompilerServices.GetConvertMethod( b.Source.Property.PropertyType ));
- else
- il.Emit(OpCodes.Unbox_Any, b.Source.Property.PropertyType);
-
- il.Emit(OpCodes.Callvirt, b.Source.Property.GetSetMethod());
- il.Emit (OpCodes.Br, endMethod);
- i++;
-
- }
- il.MarkLabel(endMethod);
- il.Emit(OpCodes.Pop);
- il.Emit(OpCodes.Ret);
-
- Delegate del = dm.CreateDelegate(ei.EventHandlerType, this);
- MethodInfo addHandler = ei.GetAddMethod ();
- addHandler.Invoke(grouped [0].Target.Instance, new object[] {del});
- }
- }
- /// <summary>
- /// Compile events expression in GOML attributes
- /// </summary>
- /// <param name="es">Event binding details</param>
- public void CompileEventSource(Binding binding)
- {
- Type sourceType = this.GetType();
-
- #region Retrieve EventHandler parameter type
- MethodInfo evtInvoke = binding.Source.Event.EventHandlerType.GetMethod ("Invoke");
- ParameterInfo[] evtParams = evtInvoke.GetParameters ();
- Type handlerArgsType = evtParams [1].ParameterType;
- #endregion
-
- Type[] args = {typeof(object), typeof(object),handlerArgsType};
- DynamicMethod dm = new DynamicMethod(binding.NewDynMethodId,
- typeof(void),
- args,
- sourceType);
-
-
- #region IL generation
- ILGenerator il = dm.GetILGenerator(256);
-
- string src = binding.Expression.Trim();
-
- if (! (src.StartsWith("{") || src.EndsWith ("}")))
- throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", binding.Source.Member.Name, binding.Expression));
-
- src = src.Substring (1, src.Length - 2);
- string[] srcLines = src.Split (new char[] { ';' });
-
- foreach (string srcLine in srcLines) {
- string statement = srcLine.Trim ();
-
- string[] operandes = statement.Split (new char[] { '=' });
- if (operandes.Length < 2) //not an affectation
- {
- continue;
- }
- string lop = operandes [0].Trim ();
- string rop = operandes [operandes.Length-1].Trim ();
-
- #region LEFT OPERANDES
- GraphicObject lopObj = this; //default left operand base object is
- //the first arg (object sender) of the event handler
-
- il.Emit(OpCodes.Ldarg_0); //load sender ref onto the stack
-
- string[] lopParts = lop.Split (new char[] { '.' });
- if (lopParts.Length > 1) {//should search also for member of es.Source
- MethodInfo FindByNameMi = typeof(GraphicObject).GetMethod("FindByName");
- for (int j = 0; j < lopParts.Length - 1; j++) {
- il.Emit (OpCodes.Ldstr, lopParts[j]);
- il.Emit(OpCodes.Callvirt, FindByNameMi);
- }
- }
-
- int i = lopParts.Length -1;
-
- MemberInfo[] lopMbis = lopObj.GetType().GetMember (lopParts[i]);
-
- if (lopMbis.Length<1)
- throw new Exception (string.Format("CROW BINDING: Member not found '{0}'", lop));
-
- OpCode lopSetOC;
- dynamic lopSetMbi;
- Type lopT = null;
- switch (lopMbis[0].MemberType) {
- case MemberTypes.Property:
- PropertyInfo lopPi = sourceType.GetProperty (lopParts[i]);
- MethodInfo dstMi = lopPi.GetSetMethod ();
- lopT = lopPi.PropertyType;
- lopSetMbi = dstMi;
- lopSetOC = OpCodes.Callvirt;
- break;
- case MemberTypes.Field:
- FieldInfo dstFi = sourceType.GetField(lopParts[i]);
- lopT = dstFi.FieldType;
- lopSetMbi = dstFi;
- lopSetOC = OpCodes.Stfld;
- break;
- default:
- throw new Exception (string.Format("GOML:member type not handle: {0}", lopParts[i]));
- }
- #endregion
-
- #region RIGHT OPERANDES
- if (rop.StartsWith("\'")){
- if (!rop.EndsWith("\'"))
- throw new Exception (string.Format
- ("GOML:malformed string constant in handler: {0}", rop));
- string strcst = rop.Substring (1, rop.Length - 2);
-
- il.Emit(OpCodes.Ldstr,strcst);
-
- }else{
- //search for a static field in left operand type named 'rop name'
- FieldInfo ropFi = lopT.GetField (rop, BindingFlags.Static|BindingFlags.Public);
- if (ropFi != null)
- {
- il.Emit (OpCodes.Ldsfld, ropFi);
- }else{
- //search if parsing methods are present
- MethodInfo lopTryParseMi = lopT.GetMethod("TryParse");
- //TODO
- }
- }
-
- #endregion
-
- //emit left operand assignment
- il.Emit(lopSetOC, lopSetMbi);
- }
-
- il.Emit(OpCodes.Ret);
-
- #endregion
-
- Delegate del = dm.CreateDelegate(binding.Source.Event.EventHandlerType,this);
- MethodInfo addHandler = binding.Source.Event.GetAddMethod ();
- addHandler.Invoke(this, new object[] {del});
- }
- /// <summary>
- /// Remove dynamic delegates by ids from dataSource
- /// and delete ref of this in Shared interface refs
- /// </summary>
- public virtual void ClearBinding(){
- foreach (Binding b in Bindings) {
- if (string.IsNullOrEmpty (b.DynMethodId))
- continue;
- MemberReference mr = null;
- if (b.Target == null)
- mr = b.Source;
- else
- mr = b.Target;
- Type dataSourceType = mr.Instance.GetType();
- EventInfo evtInfo = dataSourceType.GetEvent ("ValueChanged");
- FieldInfo evtFi = CompilerServices.GetEventHandlerField (dataSourceType, "ValueChanged");
- MulticastDelegate multicastDelegate = evtFi.GetValue (mr.Instance) as MulticastDelegate;
- if (multicastDelegate != null) {
- foreach (Delegate d in multicastDelegate.GetInvocationList()) {
- if (d.Method.Name == b.DynMethodId)
- evtInfo.RemoveEventHandler (mr.Instance, d);
- }
- }
- b.Reset ();
- }
- }
- #endregion
-
- #region IXmlSerializable
- public virtual System.Xml.Schema.XmlSchema GetSchema ()
- {
- return null;
- }
- public virtual void ReadXml (System.Xml.XmlReader reader)
- {
- if (!reader.HasAttributes)
- return;
- Type thisType = this.GetType ();
- while (reader.MoveToNextAttribute ()) {
- string attName = reader.Name;
- string attValue = reader.Value;
-
- if (string.IsNullOrEmpty (attValue))
- continue;
-
- MemberInfo mi = thisType.GetMember (attName).FirstOrDefault();
- if (mi == null) {
- Debug.WriteLine ("GOML: Unknown attribute in " + thisType.ToString() + " : " + attName);
- continue;
- }
- if (mi.MemberType == MemberTypes.Event) {
- this.Bindings.Add (new Binding (new MemberReference(this, mi), attValue));
- continue;
- }
- if (mi.MemberType == MemberTypes.Property) {
- PropertyInfo pi = mi as PropertyInfo;
-
- if (pi.GetSetMethod () == null)
- continue;
-
- bool isAttribute = false;
- object defaultValue = null;
-
- foreach (object attrib in pi.GetCustomAttributes ()) {
- XmlAttributeAttribute xaa = attrib as XmlAttributeAttribute;
- if (xaa != null) {
- isAttribute = true;
- if (!string.IsNullOrEmpty (xaa.AttributeName))
- attName = xaa.AttributeName;
- continue;
- }
- if (attrib is XmlIgnoreAttribute)
- break;
- DefaultValueAttribute dv = attrib as DefaultValueAttribute;
- if (dv != null)
- defaultValue = dv.Value;
- }
- if (!isAttribute)
- continue;
-// {
-// //avoid system types automaticaly converted by parser
-// if (defaultValue != null && !pi.PropertyType.Namespace.StartsWith("System")) {
-// if (pi.PropertyType != defaultValue.GetType()) {
-// MethodInfo miParse = pi.PropertyType.GetMethod ("Parse", BindingFlags.Static | BindingFlags.Public);
-// if (miParse != null) {
-// pi.SetValue (this, miParse.Invoke (null, new object[]{ defaultValue }), null);
-// continue;
-// }
-// }
-// }
-// pi.SetValue (this, defaultValue, null);
-// } else {
-
- if (attValue.StartsWith("{")) {
- //binding
- if (!attValue.EndsWith("}"))
- throw new Exception (string.Format("GOML:Malformed binding: {0}", attValue));
-
- this.Bindings.Add (new Binding (new MemberReference(this, pi), attValue.Substring (1, attValue.Length - 2)));
- continue;
- }
-
- if (pi.PropertyType == typeof(string)) {
- pi.SetValue (this, attValue, null);
- continue;
- }
-
- if (pi.PropertyType.IsEnum) {
- pi.SetValue (this, Enum.Parse (pi.PropertyType, attValue), null);
- } else {
- MethodInfo me = pi.PropertyType.GetMethod ("Parse", new Type[] { typeof(string) });
- pi.SetValue (this, me.Invoke (null, new string[] { attValue }), null);
- }
- }
- }
- reader.MoveToElement();
- }
- public virtual void WriteXml (System.Xml.XmlWriter writer)
- {
- foreach (PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
- if (pi.GetSetMethod () == null)
- continue;
-
- bool isAttribute = false;
- bool hasDefaultValue = false;
- bool ignore = false;
- string name = "";
- object value = null;
- Type valueType = null;
-
-
- MemberInfo mi = pi.GetGetMethod ();
-
- if (mi == null)
- continue;
-
- value = pi.GetValue (this, null);
- valueType = pi.PropertyType;
- name = pi.Name;
-
-
-
- object[] att = pi.GetCustomAttributes (false);
-
- foreach (object o in att) {
- XmlAttributeAttribute xaa = o as XmlAttributeAttribute;
- if (xaa != null) {
- isAttribute = true;
- if (string.IsNullOrEmpty (xaa.AttributeName))
- name = pi.Name;
- else
- name = xaa.AttributeName;
- continue;
- }
-
- XmlIgnoreAttribute xia = o as XmlIgnoreAttribute;
- if (xia != null) {
- ignore = true;
- continue;
- }
-
- DefaultValueAttribute dv = o as DefaultValueAttribute;
- if (dv != null) {
- if (dv.Value.Equals (value))
- hasDefaultValue = true;
- if (dv.Value.ToString () == value.ToString ())
- hasDefaultValue = true;
-
- continue;
- }
-
-
- }
-
- if (hasDefaultValue || ignore || value==null)
- continue;
-
- if (isAttribute)
- writer.WriteAttributeString (name, value.ToString ());
- else {
- if (valueType.GetInterface ("IXmlSerializable") == null)
- continue;
-
- (pi.GetValue (this, null) as IXmlSerializable).WriteXml (writer);
- }
- }
- foreach (EventInfo ei in this.GetType().GetEvents()) {
- FieldInfo fi = this.GetType().GetField(ei.Name,
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.GetField);
-
- Delegate dg = (System.Delegate)fi.GetValue (this);
-
- if (dg == null)
- continue;
-
- foreach (Delegate d in dg.GetInvocationList()) {
- if (!d.Method.Name.StartsWith ("<"))//Skipping empty handler, not clear it's trikky
- writer.WriteAttributeString (ei.Name, d.Method.Name);
- }
- }
- }
- #endregion
-
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +//using OpenTK.Graphics.OpenGL; +using System.Drawing.Imaging; +using System.Diagnostics; +using OpenTK.Input; + +using Cairo; + +using System.Xml.Serialization; +using System.Reflection; +using System.ComponentModel; +using System.IO; +//using System.Xml; +using System.Xml; +using System.Runtime.CompilerServices; +using System.Reflection.Emit; + +namespace Crow +{ + public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange + { + #if DEBUG_LAYOUTING + internal static ulong currentUid = 0; + internal ulong uid = 0; + #endif + + internal List<Binding> Bindings = new List<Binding> (); + + #region IValueChange implementation + public event EventHandler<ValueChangeEventArgs> ValueChanged; + public virtual void NotifyValueChanged(string MemberName, object _value) + { + ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value)); + } + #endregion + + #region CTOR + public GraphicObject () + { + #if DEBUG_LAYOUTING + uid = currentUid; + currentUid++; + #endif + + if (Interface.XmlSerializerInit) + return; + + loadDefaultValues (); + registerForGraphicUpdate (); + } + public GraphicObject (Rectangle _bounds) + { + if (Interface.XmlSerializerInit) + return; + + loadDefaultValues (); + Bounds = _bounds; + registerForGraphicUpdate (); + } + #endregion + + #region private fields + ILayoutable _parent; + string _name = "unamed"; + Color _background = Color.Transparent; + Color _foreground = Color.White; + Font _font = "droid, 10"; + double _cornerRadius = 0; + int _margin = 0; + bool _focusable = false; + bool _hasFocus = false; + bool _mouseRepeat; + protected bool _isVisible = true; + VerticalAlignment _verticalAlignment = VerticalAlignment.Center; + HorizontalAlignment _horizontalAlignment = HorizontalAlignment.Center; + Size _maximumSize = "0;0"; + Size _minimumSize = "0;0"; + + Picture _backgroundImage; + string _backgroundImagePath; + #endregion + + #region public fields + public GraphicObject LogicalParent; + public Rectangle Bounds; + public Rectangle Slot = new Rectangle (); + public object Tag; + public byte[] bmp; + #endregion + + #region ILayoutable + //TODO: it would save the recurent cost of a cast in event bubbling if parent type was GraphicObject + // or we could add to the interface the mouse events + [XmlIgnore]public ILayoutable Parent { + get { return _parent; } + set { +// if (_parent == value) +// return; +// if (_parent != null) +// ClearBinding (); +// + _parent = value; +// +// if (DataSource != null) +// ResolveBindings (); + } + } + + + [XmlIgnore]public virtual Rectangle ClientRectangle { + get { + Rectangle cb = Slot.Size; + cb.Inflate ( - Margin); + return cb; + } + } + [XmlIgnore]public virtual IGOLibHost HostContainer { + get { return Parent == null ? null : Parent.HostContainer; } + } + public virtual Rectangle ContextCoordinates(Rectangle r){ + return + Parent.ContextCoordinates (r);// + ClientRectangle.Position; + } + public virtual Rectangle ScreenCoordinates (Rectangle r){ + //r += Slot.Position; + + return + Parent.ScreenCoordinates(r) + Parent.getSlot().Position + Parent.ClientRectangle.Position; + } + public virtual Rectangle getSlot() + { + return Slot; + } + public virtual Rectangle getBounds() + { + return Bounds; + } + #endregion + + #region EVENT HANDLERS + public event EventHandler<MouseWheelEventArgs> MouseWheelChanged; + public event EventHandler<MouseButtonEventArgs> MouseUp; + public event EventHandler<MouseButtonEventArgs> MouseDown; + public event EventHandler<MouseButtonEventArgs> MouseClick; + public event EventHandler<MouseMoveEventArgs> MouseMove; + public event EventHandler<MouseMoveEventArgs> MouseEnter; + public event EventHandler<MouseMoveEventArgs> MouseLeave; + public event EventHandler<KeyboardKeyEventArgs> KeyDown; + public event EventHandler<KeyboardKeyEventArgs> KeyUp; + public event EventHandler Focused; + public event EventHandler Unfocused; + public event EventHandler<LayoutChangeEventArgs> LayoutChanged; + #endregion + + #region public properties + [XmlAttributeAttribute()][DefaultValue("unamed")] + public virtual string Name { + get { return _name; } + set { + if (_name == value) + return; + _name = value; + NotifyValueChanged("Name", _verticalAlignment); + } + } + [XmlAttributeAttribute ()][DefaultValue(VerticalAlignment.Center)] + public virtual VerticalAlignment VerticalAlignment { + get { return _verticalAlignment; } + set { + if (_verticalAlignment == value) + return; + + _verticalAlignment = value; + NotifyValueChanged("VerticalAlignment", _verticalAlignment); + } + } + [XmlAttributeAttribute()][DefaultValue(HorizontalAlignment.Center)] + public virtual HorizontalAlignment HorizontalAlignment { + get { return _horizontalAlignment; } + set { + if (_horizontalAlignment == value) + return; + + _horizontalAlignment = value; + NotifyValueChanged("HorizontalAlignment", _horizontalAlignment); + } + } + [XmlAttributeAttribute()][DefaultValue(0)] + public virtual int Left { + get { return Bounds.X; } + set { + if (Bounds.X == value) + return; + + Bounds.X = value; + NotifyValueChanged ("Left", Bounds.X); + this.RegisterForLayouting ((int)LayoutingType.X); + } + } + [XmlAttributeAttribute()][DefaultValue(0)] + public virtual int Top { + get { return Bounds.Y; } + set { + if (Bounds.Y == value) + return; + + Bounds.Y = value; + NotifyValueChanged ("Top", Bounds.Y); + this.RegisterForLayouting ((int)LayoutingType.Y); + } + } + [XmlAttributeAttribute()][DefaultValue(0)] + public virtual int Width { + get { return Bounds.Width; } + set { + if (Bounds.Width == value) + return; + + Bounds.Width = value; + NotifyValueChanged ("Width", Bounds.Width); + this.RegisterForLayouting ((int)LayoutingType.Width); + } + } + [XmlAttributeAttribute()][DefaultValue(0)] + public virtual int Height { + get { return Bounds.Height; } + set { + if (Bounds.Height == value) + return; + + Bounds.Height = value; + NotifyValueChanged ("Height", Bounds.Height); + this.RegisterForLayouting ((int)LayoutingType.Height); + } + } + [XmlAttributeAttribute()][DefaultValue(false)] + public virtual bool Fit { + get { return Bounds.Width < 0 && Bounds.Height < 0 ? true : false; } + set { + if (value == Fit) + return; + + Bounds.Width = Bounds.Height = -1; + } + } + [XmlAttributeAttribute()][DefaultValue(false)] + public virtual bool Focusable { + get { return _focusable; } + set { + if (_focusable == value) + return; + _focusable = value; + NotifyValueChanged ("Focusable", _focusable); + } + } + [XmlIgnore]public virtual bool HasFocus { + get { return _hasFocus; } + set { + if (value == _hasFocus) + return; + + _hasFocus = value; + NotifyValueChanged ("HasFocus", _hasFocus); + } + } + [XmlAttributeAttribute()][DefaultValue(false)] + public virtual bool MouseRepeat { + get { return _mouseRepeat; } + set { + if (_mouseRepeat == value) + return; + _mouseRepeat = value; + NotifyValueChanged ("MouseRepeat", _mouseRepeat); + } + } + [XmlAttributeAttribute()][DefaultValue("Transparent")] + public virtual Color Background { + get { return _background; } + set { + if (_background == value) + return; + _background = value; + NotifyValueChanged ("Background", _background); + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue("White")] + public virtual Color Foreground { + get { return _foreground; } + set { + if (_foreground == value) + return; + _foreground = value; + NotifyValueChanged ("Foreground", _foreground); + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue("droid,10")] + public virtual Font Font { + get { return _font; } + set { + if (value == _font) + return; + _font = value; + NotifyValueChanged ("Font", _font); + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue(0.0)] + public virtual double CornerRadius { + get { return _cornerRadius; } + set { + if (value == _cornerRadius) + return; + _cornerRadius = value; + NotifyValueChanged ("CornerRadius", _cornerRadius); + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue(0)] + public virtual int Margin { + get { return _margin; } + set { + if (value == _margin) + return; + _margin = value; + NotifyValueChanged ("Margin", _margin); + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue(true)] + public virtual bool Visible { + get { return _isVisible; } + set { + if (value == _isVisible) + return; + + _isVisible = value; + + if (HostContainer == null) + return; + //add slot to clipping to redraw + HostContainer.gobjsToRedraw.Add (this); + + //ensure main win doesn't keep hidden childrens ref + if (this.Contains (HostContainer.hoverWidget)) + HostContainer.hoverWidget = null; + if (Parent is GenericStack) + Parent.RegisterForLayouting ((int)LayoutingType.Sizing | (int)LayoutingType.PositionChildren); + + NotifyValueChanged ("Visible", _isVisible); + } + } + //TODO: only used in group, should be removed from base go object + [XmlIgnore]public virtual bool DrawingIsValid + { get { return bmp == null ? + false : + true; } } + [XmlAttributeAttribute()][DefaultValue("0;0")] + public virtual Size MaximumSize { + get { return _maximumSize; } + set { _maximumSize = value; } + } + [XmlAttributeAttribute()][DefaultValue("0;0")] + public virtual Size MinimumSize { + get { return _minimumSize; } + set { _minimumSize = value; } + } + object dataSource; + + [XmlIgnore]public virtual object DataSource { + set { + if (dataSource == value) + return; + + if (dataSource != null) + this.ClearBinding (); + + dataSource = value; + + if (dataSource != null) + this.ResolveBindings(); + } + get { + return dataSource == null ? + LogicalParent == null ? + Parent is GraphicObject ? (Parent as GraphicObject).DataSource : null : LogicalParent.DataSource : dataSource; + } + } + #endregion + + + /// <summary> + /// Loads the default values from XML attributes default + /// </summary> + protected virtual void loadDefaultValues() + { + foreach (PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { + if (pi.GetSetMethod () == null) + continue; + string name = ""; + + object[] att = pi.GetCustomAttributes (false); + + foreach (object o in att) { + XmlAttributeAttribute xaa = o as XmlAttributeAttribute; + if (xaa != null) { + if (string.IsNullOrEmpty (xaa.AttributeName)) + name = pi.Name; + else + name = xaa.AttributeName; + continue; + } + + XmlIgnoreAttribute xia = o as XmlIgnoreAttribute; + if (xia != null) + continue; + + DefaultValueAttribute dv = o as DefaultValueAttribute; + if (dv != null) { + object defaultValue = dv.Value; + //avoid system types automaticaly converted by parser + if (defaultValue != null && !pi.PropertyType.Namespace.StartsWith("System")) { + if (pi.PropertyType != defaultValue.GetType()) { + MethodInfo miParse = pi.PropertyType.GetMethod ("Parse", BindingFlags.Static | BindingFlags.Public); + if (miParse != null) { + pi.SetValue (this, miParse.Invoke (null, new object[]{ defaultValue }), null); + continue; + } + } + } + pi.SetValue (this, defaultValue, null); + } + } + } + } + + public virtual GraphicObject FindByName(string nameToFind){ + return nameToFind == _name ? this : null; + } + public virtual bool Contains(GraphicObject goToFind){ + return false; + } + + + /// <summary> + /// Clear chached object and add clipping region in redraw list of interface + /// </summary> + public virtual void registerForGraphicUpdate () + { + bmp = null; + if (HostContainer != null) + HostContainer.gobjsToRedraw.Add (this); + } + /// <summary> + /// Add clipping region in redraw list of interface, dont update cached object content + /// </summary> + public virtual void RegisterForRedraw () + { + if (HostContainer != null) + HostContainer.gobjsToRedraw.Add (this); + } + + /// <summary> + /// keep last slot components for each layouting pass to track + /// changes and trigger update of other component accordingly + /// </summary> + public Rectangle LastSlots; + /// <summary> + /// keep last slot painted on screen to clear traces if moved or resized + /// TODO: we should ensure the whole parsed widget tree is the last painted + /// version to clear effective oldslot if parents have been moved or resized. + /// IDEA is to add a ScreenCoordinates function that use only lastPaintedSlots + /// </summary> + public Rectangle LastPaintedSlot; + + public virtual void registerClipRect() + { + HostContainer.redrawClip.AddRectangle (ScreenCoordinates(Slot)); + //this clipping should take only last painted slots in ancestor tree which + //is not the case for now. + HostContainer.redrawClip.AddRectangle (ScreenCoordinates(LastPaintedSlot)); + } + /// <summary> return size of content + margins </summary> + protected virtual Size measureRawSize () + { + return Bounds.Size; + } + /// <summary> clear current layoutingQueue items for object and + /// trigger a new layouting pass for a layoutType </summary> + public virtual void RegisterForLayouting(int layoutType) + { + if (Parent == null) + return; + #if DEBUG_LAYOUTING + Debug.WriteLine ("RegisterForLayouting => {1}->{0}", layoutType, this.ToString()); + #endif + lock (Interface.LayoutingQueue) { + 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 if (Bounds.Width < 0) //fit + Interface.LayoutingQueue.EnqueueBeforeParentSizing (LayoutingType.Width, this); + else + Interface.LayoutingQueue.Insert (0, new LayoutingQueueItem (LayoutingType.Width, this)); + } + + if ((layoutType & (int)LayoutingType.Height) > 0) { + if (Bounds.Height == 0) //stretch in parent + Interface.LayoutingQueue.EnqueueAfterParentSizing (LayoutingType.Height, this); + else if (Bounds.Height < 0) //fit + Interface.LayoutingQueue.EnqueueBeforeParentSizing (LayoutingType.Height, this); + else + Interface.LayoutingQueue.Insert (0, new LayoutingQueueItem (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); + } + } + + /// <summary> trigger dependant sizing component update </summary> + public virtual void OnLayoutChanges(LayoutingType layoutType) + { + if (Parent==null) + return; + #if DEBUG_LAYOUTING + Debug.WriteLine ("Layout change: " + this.ToString () + ":" + LastSlots.ToString() + "=>" + Slot.ToString ()); + #endif + + switch (layoutType) { + case LayoutingType.Width: + if (Parent.getBounds ().Width < 0) { + Group gw = Parent as Group; + if (gw != null) { + if (Slot.Width > gw.maxChildrenWidth) + gw.maxChildrenWidth = Slot.Width; + } + this.Parent.RegisterForLayouting ((int)LayoutingType.Width); + }else if (Width != 0) //update position in parent + this.RegisterForLayouting ((int)LayoutingType.X); + GenericStack gsw = Parent as GenericStack; + if (gsw == null) + break; + if ((Parent as GenericStack).Orientation == Orientation.Horizontal) { +// ulong idx = (ulong)gsw.Children.IndexOf (this); +// if (idx < gsw.stackingUpdateStartIndex) +// gsw.stackingUpdateStartIndex = idx; + this.Parent.RegisterForLayouting ((int)LayoutingType.PositionChildren); + } + break; + case LayoutingType.Height: + if (Parent.getBounds ().Height < 0) { + Group gh = Parent as Group; + if (gh != null) { + if (Slot.Width > gh.maxChildrenHeight) + gh.maxChildrenHeight = Slot.Height; + } + this.Parent.RegisterForLayouting ((int)LayoutingType.Height); + }else if (Height != 0) //update position in parent + this.RegisterForLayouting ((int)LayoutingType.Y); + GenericStack gsh = Parent as GenericStack; + if (gsh==null) + break; + if (gsh.Orientation == Orientation.Vertical) { +// ulong idx = (ulong)gsh.Children.IndexOf (this); +// if (idx < gsh.stackingUpdateStartIndex) +// gsh.stackingUpdateStartIndex = idx; + this.Parent.RegisterForLayouting ((int)LayoutingType.PositionChildren); + } + break; + } + LayoutChanged.Raise (this, new LayoutChangeEventArgs (layoutType)); + } + /// <summary> Update layout component, this is where the computation of alignement + /// and size take place </summary> + public virtual void UpdateLayout (LayoutingType layoutType) + { + switch (layoutType) { + case LayoutingType.X: + if (Bounds.X == 0) { + switch (HorizontalAlignment) { + case HorizontalAlignment.Left: + Slot.X = 0; + break; + case HorizontalAlignment.Right: + Slot.X = Parent.ClientRectangle.Width - Slot.Width; + break; + case HorizontalAlignment.Center: + Slot.X = Parent.ClientRectangle.Width / 2 - Slot.Width / 2; + break; + } + } else + Slot.X = Bounds.X; + + if (LastSlots.X == Slot.X) + break; + + bmp = null; + + OnLayoutChanges (layoutType); + + LastSlots.X = Slot.X; + break; + case LayoutingType.Y: + if (Bounds.Y == 0) { + switch (VerticalAlignment) { + case VerticalAlignment.Top: + Slot.Y = 0; + break; + case VerticalAlignment.Bottom: + Slot.Y = Parent.ClientRectangle.Height - Slot.Height; + break; + case VerticalAlignment.Center: + Slot.Y = Parent.ClientRectangle.Height / 2 - Slot.Height / 2; + break; + } + }else + Slot.Y = Bounds.Y; + + if (LastSlots.Y == Slot.Y) + break; + + bmp = null; + + OnLayoutChanges (layoutType); + + 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 + Slot.Width = Parent.ClientRectangle.Width; + + //size constrain + if (Slot.Width < MinimumSize.Width) + Slot.Width = MinimumSize.Width; + else if (Slot.Width > MaximumSize.Width && MaximumSize.Width > 0) + Slot.Width = MaximumSize.Width; + + if (LastSlots.Width == Slot.Width) + break; + + bmp = null; + + OnLayoutChanges (layoutType); + + 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 + Slot.Height = Parent.ClientRectangle.Height; + + //size constrain + if (Slot.Height < MinimumSize.Height) + Slot.Height = MinimumSize.Height; + else if (Slot.Height > MaximumSize.Height && MaximumSize.Height > 0) + Slot.Height = MaximumSize.Height; + + + if (LastSlots.Height == Slot.Height) + break; + + bmp = null; + + OnLayoutChanges (layoutType); + + LastSlots.Height = Slot.Height; + break; + } + lock (Interface.LayoutingQueue) { + //if no layouting remains in queue for item, registre for redraw + if (Interface.LayoutingQueue.Where (lq => lq.GraphicObject == this).Count () <= 0 && bmp == null) + this.RegisterForRedraw (); + } + } + + /// <summary> This is the common overridable drawing routine to create new widget </summary> + protected virtual void onDraw(Context gr) + { + Rectangle rBack = new Rectangle (Slot.Size); + + Background.SetAsSource (gr); + CairoHelpers.CairoRectangle(gr,rBack,_cornerRadius); + gr.Fill (); + } + + /// <summary> + /// Interfal drawing context creation on a cached surface limited to slot size + /// this trigger the effective drawing routine </summary> + protected virtual void UpdateGraphic () + { + LastPaintedSlot = Slot; + + int stride = 4 * Slot.Width; + + int bmpSize = Math.Abs (stride) * Slot.Height; + bmp = new byte[bmpSize]; + + using (ImageSurface draw = + new ImageSurface(bmp, Format.Argb32, Slot.Width, Slot.Height, stride)) { + using (Context gr = new Context (draw)) { + gr.Antialias = Antialias.Subpixel; + onDraw (gr); + } + draw.Flush (); + //draw.WriteToPng ("/mnt/data/test.png"); + } + } + /// <summary> Chained painting routine on the parent context of the actual cached version + /// of the widget </summary> + public virtual void Paint (ref Context ctx, Rectangles clip = null) + { + if (!Visible) + return; + + if (bmp == null) + UpdateGraphic (); + + Rectangle rb = Parent.ContextCoordinates(Slot); + + using (ImageSurface source = new ImageSurface(bmp, Format.Argb32, Slot.Width, Slot.Height, 4 * Slot.Width)) { + if (this.Background == Color.Clear) { + ctx.Save (); + ctx.Operator = Operator.Clear; + ctx.Rectangle(rb); + ctx.Fill (); + ctx.Restore (); + } + ctx.SetSourceSurface (source, rb.X, rb.Y); + ctx.Paint (); + } + } + + #region Keyboard handling + public virtual void onKeyDown(object sender, KeyboardKeyEventArgs e){ + KeyDown.Raise (sender, e); + } + #endregion + + #region Mouse handling + public virtual bool MouseIsIn(Point m) + { + if (!Visible) + return false; + if (ScreenCoordinates (Slot).ContainsOrIsEqual (m)) { + Scroller scr = Parent as Scroller; + if (scr == null) + return true; + return scr.MouseIsIn (scr.savedMousePos); + } + return false; + } + public virtual void checkHoverWidget(MouseMoveEventArgs e) + { + IGOLibHost glh = HostContainer; + if (glh.hoverWidget != this) { + glh.hoverWidget = this; + onMouseEnter (this, e); + } + + this.onMouseMove (this, e); + } + public virtual void onMouseMove(object sender, MouseMoveEventArgs e) + { + //bubble event to the top + GraphicObject p = Parent as GraphicObject; + if (p != null) + p.onMouseMove(sender,e); + + MouseMove.Raise (sender, e); + } + public virtual void onMouseDown(object sender, MouseButtonEventArgs e){ + IGOLibHost hc = HostContainer; + if (hc.activeWidget == null) + hc.activeWidget = this; + if (this.Focusable && !Interface.FocusOnHover) { + BubblingMouseButtonEventArg be = e as BubblingMouseButtonEventArg; + if (be.Focused == null) { + be.Focused = this; + hc.FocusedWidget = this; + } + } + //bubble event to the top + GraphicObject p = Parent as GraphicObject; + if (p != null) + p.onMouseDown(sender,e); + + MouseDown.Raise (this, e); + } + public virtual void onMouseUp(object sender, MouseButtonEventArgs e){ + //bubble event to the top + GraphicObject p = Parent as GraphicObject; + if (p != null) + p.onMouseUp(sender,e); + + MouseUp.Raise (this, e); + + if (MouseIsIn (e.Position)&&HasFocus) + onMouseClick(sender,e); + } + public virtual void onMouseClick(object sender, MouseButtonEventArgs e){ + MouseClick.Raise (this, e); + } + public virtual void onMouseWheel(object sender, MouseWheelEventArgs e){ + GraphicObject p = Parent as GraphicObject; + if (p != null) + p.onMouseWheel(this,e); + + MouseWheelChanged.Raise (this, e); + } + public virtual void onFocused(object sender, EventArgs e){ + Focused.Raise (this, e); + this.HasFocus = true; + } + public virtual void onUnfocused(object sender, EventArgs e){ + Unfocused.Raise (this, e); + this.HasFocus = false; + } + public virtual void onMouseEnter(object sender, MouseMoveEventArgs e) + { + MouseEnter.Raise (this, e); + } + public virtual void onMouseLeave(object sender, MouseMoveEventArgs e) + { + MouseLeave.Raise (this, e); + } + #endregion + + public override string ToString () + { + string tmp =""; + + if (Parent != null) + tmp = Parent.ToString () + tmp; + #if DEBUG_LAYOUTING + return Name == "unamed" ? tmp + "." + this.GetType ().Name + uid.ToString(): tmp + "." + Name; + #else + return Name == "unamed" ? tmp + "." + this.GetType ().Name : tmp + "." + Name; + #endif + } + + #region Binding + public virtual void ResolveBindings() + { + #if DEBUG_BINDING + Debug.WriteLine ("ResolveBinding => " + this.ToString ()); + #endif + List<Binding> resolved = new List<Binding> (); + foreach (Binding b in Bindings) { + if (!string.IsNullOrEmpty (b.DynMethodId)) + continue; + if (b.Source.Member.MemberType == MemberTypes.Event) { + if (b.Expression.StartsWith("{")){ + CompileEventSource(b); + continue; + } + } + if (!b.FindTarget ()) + 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); + continue; + } + + MethodInfo addHandler = b.Source.Event.GetAddMethod (); + Delegate del = Delegate.CreateDelegate (b.Source.Event.EventHandlerType, b.Target.Instance, b.Target.Method); + addHandler.Invoke (this, new object[] { del }); + continue; + } + resolved.Add (b); + } + //group;only one dynMethods by target (valuechanged event source) + //changed value name tested in switch + IEnumerable<Binding[]> groupedByTarget = resolved.GroupBy (g => g.Target.Instance, g => g, (k, g) => g.ToArray ()); + foreach (Binding[] grouped in groupedByTarget) { + int i = 0; + Type targetType = grouped[0].Target.Instance.GetType(); + Type sourceType = this.GetType(); + + DynamicMethod dm = null; + ILGenerator il = null; + + MethodInfo stringEquals = typeof(string).GetMethod + ("op_Equality", new Type[2] {typeof(string), typeof(string)}); + + + System.Reflection.Emit.Label[] jumpTable = null; + System.Reflection.Emit.Label endMethod = new System.Reflection.Emit.Label(); + + #region Retrieve EventHandler parameter type + EventInfo ei = targetType.GetEvent ("ValueChanged"); + //no dynamic update if ValueChanged interface is not implemented + if (ei != null){ + MethodInfo evtInvoke = ei.EventHandlerType.GetMethod ("Invoke"); + ParameterInfo[] evtParams = evtInvoke.GetParameters (); + Type handlerArgsType = evtParams [1].ParameterType; + + Type[] args = {typeof(object), typeof(object),handlerArgsType}; + dm = new DynamicMethod(grouped[0].NewDynMethodId, + MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot, + CallingConventions.Standard, + typeof(void), + args, + sourceType,true); + + il = dm.GetILGenerator(256); + + endMethod = il.DefineLabel(); + jumpTable = new System.Reflection.Emit.Label[grouped.Length]; + for (i = 0; i < grouped.Length; i++) + jumpTable [i] = il.DefineLabel (); + il.DeclareLocal(typeof(string)); + il.DeclareLocal(typeof(object)); + + il.Emit(OpCodes.Nop); + il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Isinst, sourceType); + //push new value onto stack + il.Emit(OpCodes.Ldarg_2); + FieldInfo fiNewValue = typeof(ValueChangeEventArgs).GetField("NewValue"); + il.Emit(OpCodes.Ldfld, fiNewValue); + il.Emit(OpCodes.Stloc_1); + //push name + il.Emit(OpCodes.Ldarg_2); + FieldInfo fiMbName = typeof(ValueChangeEventArgs).GetField("MemberName"); + il.Emit(OpCodes.Ldfld, fiMbName); + il.Emit(OpCodes.Stloc_0); + il.Emit(OpCodes.Ldloc_0); + il.Emit(OpCodes.Brfalse, endMethod); + } + #endregion + + i = 0; + foreach (Binding b in grouped) { + #region initialize target with actual value + object targetValue = null; + if (b.Target.Member != null){ + if (b.Target.Member.MemberType == MemberTypes.Property) + targetValue = b.Target.Property.GetGetMethod ().Invoke (b.Target.Instance, null); + else if (b.Target.Member.MemberType == MemberTypes.Field) + targetValue = b.Target.Field.GetValue (b.Target.Instance); + else if (b.Target.Member.MemberType == MemberTypes.Method){ + MethodInfo mthSrc = b.Target.Method; + if (mthSrc.IsDefined(typeof(ExtensionAttribute), false)) + targetValue = mthSrc.Invoke(null, new object[] {b.Target.Instance}); + else + targetValue = mthSrc.Invoke(b.Target.Instance, null); + }else + throw new Exception ("unandled source member type for binding"); + }else if (string.IsNullOrEmpty(b.Expression)) + targetValue= grouped [0].Target.Instance;//empty binding exp=> bound to target object by default + //TODO: handle other dest type conversions + if (b.Source.Property.PropertyType == typeof(string)){ + if (targetValue == null){ + //set default value + + }else + targetValue = targetValue.ToString (); + } + b.Source.Property.GetSetMethod ().Invoke (this, new object[] { targetValue }); + #endregion + + //if no dyn update, skip jump table + if (il == null) + continue; + + il.Emit (OpCodes.Ldloc_0); + if (b.Target.Member != null) + il.Emit (OpCodes.Ldstr, b.Target.Member.Name); + else + il.Emit (OpCodes.Ldstr, b.Expression.Split('/').LastOrDefault()); + il.Emit (OpCodes.Callvirt, stringEquals); + il.Emit (OpCodes.Brtrue, jumpTable[i]); + i++; + } + + if (il == null) + continue; + + il.Emit (OpCodes.Br, endMethod); + + i = 0; + foreach (Binding b in grouped) { + + il.MarkLabel (jumpTable [i]); + il.Emit(OpCodes.Ldloc_1); + + //by default, target value type is deducted from source member type to allow + //memberless binding, if targetMember exists, it will be used to determine target + //value type for conversion + Type targetValueType = b.Source.Property.PropertyType; + if (b.Target.Member != null) { + if (b.Target.Member.MemberType == MemberTypes.Property) + targetValueType = b.Target.Property.PropertyType; + else if (b.Target.Member.MemberType == MemberTypes.Field) + targetValueType = b.Target.Field.FieldType; + else + throw new Exception ("unhandle target member type in binding"); + } + + if (!targetValueType.IsValueType) + il.Emit(OpCodes.Castclass, targetValueType); + else if (b.Source.Property.PropertyType != targetValueType) + il.Emit(OpCodes.Callvirt, CompilerServices.GetConvertMethod( b.Source.Property.PropertyType )); + else + il.Emit(OpCodes.Unbox_Any, b.Source.Property.PropertyType); + + il.Emit(OpCodes.Callvirt, b.Source.Property.GetSetMethod()); + il.Emit (OpCodes.Br, endMethod); + i++; + + } + il.MarkLabel(endMethod); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ret); + + Delegate del = dm.CreateDelegate(ei.EventHandlerType, this); + MethodInfo addHandler = ei.GetAddMethod (); + addHandler.Invoke(grouped [0].Target.Instance, new object[] {del}); + } + } + /// <summary> + /// Compile events expression in GOML attributes + /// </summary> + /// <param name="es">Event binding details</param> + public void CompileEventSource(Binding binding) + { + Type sourceType = this.GetType(); + + #region Retrieve EventHandler parameter type + MethodInfo evtInvoke = binding.Source.Event.EventHandlerType.GetMethod ("Invoke"); + ParameterInfo[] evtParams = evtInvoke.GetParameters (); + Type handlerArgsType = evtParams [1].ParameterType; + #endregion + + Type[] args = {typeof(object), typeof(object),handlerArgsType}; + DynamicMethod dm = new DynamicMethod(binding.NewDynMethodId, + typeof(void), + args, + sourceType); + + + #region IL generation + ILGenerator il = dm.GetILGenerator(256); + + string src = binding.Expression.Trim(); + + if (! (src.StartsWith("{") || src.EndsWith ("}"))) + throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", binding.Source.Member.Name, binding.Expression)); + + src = src.Substring (1, src.Length - 2); + string[] srcLines = src.Split (new char[] { ';' }); + + foreach (string srcLine in srcLines) { + string statement = srcLine.Trim (); + + string[] operandes = statement.Split (new char[] { '=' }); + if (operandes.Length < 2) //not an affectation + { + continue; + } + string lop = operandes [0].Trim (); + string rop = operandes [operandes.Length-1].Trim (); + + #region LEFT OPERANDES + GraphicObject lopObj = this; //default left operand base object is + //the first arg (object sender) of the event handler + + il.Emit(OpCodes.Ldarg_0); //load sender ref onto the stack + + string[] lopParts = lop.Split (new char[] { '.' }); + if (lopParts.Length > 1) {//should search also for member of es.Source + MethodInfo FindByNameMi = typeof(GraphicObject).GetMethod("FindByName"); + for (int j = 0; j < lopParts.Length - 1; j++) { + il.Emit (OpCodes.Ldstr, lopParts[j]); + il.Emit(OpCodes.Callvirt, FindByNameMi); + } + } + + int i = lopParts.Length -1; + + MemberInfo[] lopMbis = lopObj.GetType().GetMember (lopParts[i]); + + if (lopMbis.Length<1) + throw new Exception (string.Format("CROW BINDING: Member not found '{0}'", lop)); + + OpCode lopSetOC; + dynamic lopSetMbi; + Type lopT = null; + switch (lopMbis[0].MemberType) { + case MemberTypes.Property: + PropertyInfo lopPi = sourceType.GetProperty (lopParts[i]); + MethodInfo dstMi = lopPi.GetSetMethod (); + lopT = lopPi.PropertyType; + lopSetMbi = dstMi; + lopSetOC = OpCodes.Callvirt; + break; + case MemberTypes.Field: + FieldInfo dstFi = sourceType.GetField(lopParts[i]); + lopT = dstFi.FieldType; + lopSetMbi = dstFi; + lopSetOC = OpCodes.Stfld; + break; + default: + throw new Exception (string.Format("GOML:member type not handle: {0}", lopParts[i])); + } + #endregion + + #region RIGHT OPERANDES + if (rop.StartsWith("\'")){ + if (!rop.EndsWith("\'")) + throw new Exception (string.Format + ("GOML:malformed string constant in handler: {0}", rop)); + string strcst = rop.Substring (1, rop.Length - 2); + + il.Emit(OpCodes.Ldstr,strcst); + + }else{ + //search for a static field in left operand type named 'rop name' + FieldInfo ropFi = lopT.GetField (rop, BindingFlags.Static|BindingFlags.Public); + if (ropFi != null) + { + il.Emit (OpCodes.Ldsfld, ropFi); + }else{ + //search if parsing methods are present + MethodInfo lopTryParseMi = lopT.GetMethod("TryParse"); + //TODO + } + } + + #endregion + + //emit left operand assignment + il.Emit(lopSetOC, lopSetMbi); + } + + il.Emit(OpCodes.Ret); + + #endregion + + Delegate del = dm.CreateDelegate(binding.Source.Event.EventHandlerType,this); + MethodInfo addHandler = binding.Source.Event.GetAddMethod (); + addHandler.Invoke(this, new object[] {del}); + } + /// <summary> + /// Remove dynamic delegates by ids from dataSource + /// and delete ref of this in Shared interface refs + /// </summary> + public virtual void ClearBinding(){ + foreach (Binding b in Bindings) { + if (string.IsNullOrEmpty (b.DynMethodId)) + continue; + MemberReference mr = null; + if (b.Target == null) + mr = b.Source; + else + mr = b.Target; + Type dataSourceType = mr.Instance.GetType(); + EventInfo evtInfo = dataSourceType.GetEvent ("ValueChanged"); + FieldInfo evtFi = CompilerServices.GetEventHandlerField (dataSourceType, "ValueChanged"); + MulticastDelegate multicastDelegate = evtFi.GetValue (mr.Instance) as MulticastDelegate; + if (multicastDelegate != null) { + foreach (Delegate d in multicastDelegate.GetInvocationList()) { + if (d.Method.Name == b.DynMethodId) + evtInfo.RemoveEventHandler (mr.Instance, d); + } + } + b.Reset (); + } + } + #endregion + + #region IXmlSerializable + public virtual System.Xml.Schema.XmlSchema GetSchema () + { + return null; + } + public virtual void ReadXml (System.Xml.XmlReader reader) + { + if (!reader.HasAttributes) + return; + Type thisType = this.GetType (); + while (reader.MoveToNextAttribute ()) { + string attName = reader.Name; + string attValue = reader.Value; + + if (string.IsNullOrEmpty (attValue)) + continue; + + MemberInfo mi = thisType.GetMember (attName).FirstOrDefault(); + if (mi == null) { + Debug.WriteLine ("GOML: Unknown attribute in " + thisType.ToString() + " : " + attName); + continue; + } + if (mi.MemberType == MemberTypes.Event) { + this.Bindings.Add (new Binding (new MemberReference(this, mi), attValue)); + continue; + } + if (mi.MemberType == MemberTypes.Property) { + PropertyInfo pi = mi as PropertyInfo; + + if (pi.GetSetMethod () == null) + continue; + + bool isAttribute = false; + object defaultValue = null; + + foreach (object attrib in pi.GetCustomAttributes ()) { + XmlAttributeAttribute xaa = attrib as XmlAttributeAttribute; + if (xaa != null) { + isAttribute = true; + if (!string.IsNullOrEmpty (xaa.AttributeName)) + attName = xaa.AttributeName; + continue; + } + if (attrib is XmlIgnoreAttribute) + break; + DefaultValueAttribute dv = attrib as DefaultValueAttribute; + if (dv != null) + defaultValue = dv.Value; + } + if (!isAttribute) + continue; +// { +// //avoid system types automaticaly converted by parser +// if (defaultValue != null && !pi.PropertyType.Namespace.StartsWith("System")) { +// if (pi.PropertyType != defaultValue.GetType()) { +// MethodInfo miParse = pi.PropertyType.GetMethod ("Parse", BindingFlags.Static | BindingFlags.Public); +// if (miParse != null) { +// pi.SetValue (this, miParse.Invoke (null, new object[]{ defaultValue }), null); +// continue; +// } +// } +// } +// pi.SetValue (this, defaultValue, null); +// } else { + + if (attValue.StartsWith("{")) { + //binding + if (!attValue.EndsWith("}")) + throw new Exception (string.Format("GOML:Malformed binding: {0}", attValue)); + + this.Bindings.Add (new Binding (new MemberReference(this, pi), attValue.Substring (1, attValue.Length - 2))); + continue; + } + + if (pi.PropertyType == typeof(string)) { + pi.SetValue (this, attValue, null); + continue; + } + + if (pi.PropertyType.IsEnum) { + pi.SetValue (this, Enum.Parse (pi.PropertyType, attValue), null); + } else { + MethodInfo me = pi.PropertyType.GetMethod ("Parse", new Type[] { typeof(string) }); + pi.SetValue (this, me.Invoke (null, new string[] { attValue }), null); + } + } + } + reader.MoveToElement(); + } + public virtual void WriteXml (System.Xml.XmlWriter writer) + { + foreach (PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { + if (pi.GetSetMethod () == null) + continue; + + bool isAttribute = false; + bool hasDefaultValue = false; + bool ignore = false; + string name = ""; + object value = null; + Type valueType = null; + + + MemberInfo mi = pi.GetGetMethod (); + + if (mi == null) + continue; + + value = pi.GetValue (this, null); + valueType = pi.PropertyType; + name = pi.Name; + + + + object[] att = pi.GetCustomAttributes (false); + + foreach (object o in att) { + XmlAttributeAttribute xaa = o as XmlAttributeAttribute; + if (xaa != null) { + isAttribute = true; + if (string.IsNullOrEmpty (xaa.AttributeName)) + name = pi.Name; + else + name = xaa.AttributeName; + continue; + } + + XmlIgnoreAttribute xia = o as XmlIgnoreAttribute; + if (xia != null) { + ignore = true; + continue; + } + + DefaultValueAttribute dv = o as DefaultValueAttribute; + if (dv != null) { + if (dv.Value.Equals (value)) + hasDefaultValue = true; + if (dv.Value.ToString () == value.ToString ()) + hasDefaultValue = true; + + continue; + } + + + } + + if (hasDefaultValue || ignore || value==null) + continue; + + if (isAttribute) + writer.WriteAttributeString (name, value.ToString ()); + else { + if (valueType.GetInterface ("IXmlSerializable") == null) + continue; + + (pi.GetValue (this, null) as IXmlSerializable).WriteXml (writer); + } + } + foreach (EventInfo ei in this.GetType().GetEvents()) { + FieldInfo fi = this.GetType().GetField(ei.Name, + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.GetField); + + Delegate dg = (System.Delegate)fi.GetValue (this); + + if (dg == null) + continue; + + foreach (Delegate d in dg.GetInvocationList()) { + if (!d.Method.Name.StartsWith ("<"))//Skipping empty handler, not clear it's trikky + writer.WriteAttributeString (ei.Name, d.Method.Name); + } + } + } + #endregion + + } +} diff --git a/src/GraphicObjects/Grid.cs b/src/GraphicObjects/Grid.cs index a3233c96..6ce9a3c5 100644 --- a/src/GraphicObjects/Grid.cs +++ b/src/GraphicObjects/Grid.cs @@ -1,149 +1,149 @@ -using System;
-using System.Diagnostics;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
- /// <summary>
- /// Simple grid container
- /// Allow symetric placement of children on a grid,
- /// excedental child (above grid sizing) are ignored
- /// and invisible child keep their place in the grid
- /// </summary>
- public class Grid : Group
- {
- #region CTOR
- public Grid()
- : base()
- {
- }
- #endregion
-
- #region Private fields
- int _spacing;
- int _columnCount;
- int _rowCount;
- #endregion
-
- public override T addChild<T> (T child)
- {
- T tmp = base.addChild (child);
- this.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- return tmp;
- }
- public override void removeChild (GraphicObject child)
- {
- base.removeChild (child);
- this.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- }
-
- #region Public Properties
- [XmlAttributeAttribute()][DefaultValue(2)]
- public int Spacing
- {
- get { return _spacing; }
- set { _spacing = value; }
- }
- [XmlAttributeAttribute()][DefaultValue(1)]
- public virtual int ColumnCount
- {
- get { return _columnCount; }
- set {
- if (_columnCount == value)
- return;
-
- _columnCount = value;
-
- NotifyValueChanged ("ColumnCount", ColumnCount);
- this.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(1)]
- public virtual int RowCount
- {
- get { return _rowCount; }
- set {
- if (_rowCount == value)
- return;
-
- _rowCount = value;
-
- NotifyValueChanged ("RowCount", RowCount);
- this.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- }
- }
- public virtual int CaseWidth {
- get { return (Slot.Width - (ColumnCount - 1) * Spacing) / ColumnCount; }
- }
- public virtual int CaseHeight {
- get { return (Slot.Height - (RowCount - 1) * Spacing) / RowCount; }
- }
-
- #endregion
-
- #region GraphicObject Overrides
-// protected override Size measureRawSize ()
-// {
-// Size tmp = new Size ();
-//
-// foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) {
-// tmp.Width = Math.Max (tmp.Width, c.Slot.Width);
-// tmp.Height = Math.Max (tmp.Height, c.Slot.Height);
-// }
-//
-// tmp.Width *= (ColumnCount - 1) * Spacing / ColumnCount;;
-// tmp.Height *= (RowCount - 1) * Spacing / RowCount;
-// tmp.Width += 2 * Margin;
-// tmp.Height += 2 * Margin;
-//
-// return tmp;
-// }
- public virtual void ComputeChildrenPositions()
- {
- int slotWidth = CaseWidth;
- int slotHeight = CaseHeight;
- for (int curY = 0; curY < RowCount; curY++) {
- for (int curX = 0; curX < ColumnCount; curX++) {
- int idx = curY * ColumnCount + curX;
- if (idx >= Children.Count)
- return;
- GraphicObject c = Children [idx];
- if (!c.Visible)
- continue;
- //ensure Item are not realigned
- c.HorizontalAlignment = HorizontalAlignment.Left;
- c.VerticalAlignment = VerticalAlignment.Top;
- c.Left = curX * (slotWidth + Spacing);
- c.Top = curY * (slotHeight + Spacing);
- c.Width = slotWidth;
- c.Height = slotHeight;
- }
- }
- }
-
- public override void RegisterForLayouting (int layoutType)
- {
- base.RegisterForLayouting (layoutType);
-
- if ((layoutType & (int)LayoutingType.PositionChildren) > 0)
- Interface.LayoutingQueue.Enqueue (LayoutingType.PositionChildren, this);
- }
- public override void UpdateLayout (LayoutingType layoutType)
- {
- if (layoutType == LayoutingType.PositionChildren) {
- ComputeChildrenPositions ();
- //if no layouting remains in queue for item, registre for redraw
- if (Interface.LayoutingQueue.Where (lq => lq.GraphicObject == this).Count () <= 0 && bmp==null)
- this.RegisterForRedraw ();
- }else
- base.UpdateLayout(layoutType);
- }
- #endregion
-
-
- }
-}
+using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; +using System.ComponentModel; + +namespace Crow +{ + /// <summary> + /// Simple grid container + /// Allow symetric placement of children on a grid, + /// excedental child (above grid sizing) are ignored + /// and invisible child keep their place in the grid + /// </summary> + public class Grid : Group + { + #region CTOR + public Grid() + : base() + { + } + #endregion + + #region Private fields + int _spacing; + int _columnCount; + int _rowCount; + #endregion + + public override T addChild<T> (T child) + { + T tmp = base.addChild (child); + this.RegisterForLayouting ((int)LayoutingType.PositionChildren); + return tmp; + } + public override void removeChild (GraphicObject child) + { + base.removeChild (child); + this.RegisterForLayouting ((int)LayoutingType.PositionChildren); + } + + #region Public Properties + [XmlAttributeAttribute()][DefaultValue(2)] + public int Spacing + { + get { return _spacing; } + set { _spacing = value; } + } + [XmlAttributeAttribute()][DefaultValue(1)] + public virtual int ColumnCount + { + get { return _columnCount; } + set { + if (_columnCount == value) + return; + + _columnCount = value; + + NotifyValueChanged ("ColumnCount", ColumnCount); + this.RegisterForLayouting ((int)LayoutingType.PositionChildren); + } + } + [XmlAttributeAttribute()][DefaultValue(1)] + public virtual int RowCount + { + get { return _rowCount; } + set { + if (_rowCount == value) + return; + + _rowCount = value; + + NotifyValueChanged ("RowCount", RowCount); + this.RegisterForLayouting ((int)LayoutingType.PositionChildren); + } + } + public virtual int CaseWidth { + get { return (Slot.Width - (ColumnCount - 1) * Spacing) / ColumnCount; } + } + public virtual int CaseHeight { + get { return (Slot.Height - (RowCount - 1) * Spacing) / RowCount; } + } + + #endregion + + #region GraphicObject Overrides +// protected override Size measureRawSize () +// { +// Size tmp = new Size (); +// +// foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { +// tmp.Width = Math.Max (tmp.Width, c.Slot.Width); +// tmp.Height = Math.Max (tmp.Height, c.Slot.Height); +// } +// +// tmp.Width *= (ColumnCount - 1) * Spacing / ColumnCount;; +// tmp.Height *= (RowCount - 1) * Spacing / RowCount; +// tmp.Width += 2 * Margin; +// tmp.Height += 2 * Margin; +// +// return tmp; +// } + public virtual void ComputeChildrenPositions() + { + int slotWidth = CaseWidth; + int slotHeight = CaseHeight; + for (int curY = 0; curY < RowCount; curY++) { + for (int curX = 0; curX < ColumnCount; curX++) { + int idx = curY * ColumnCount + curX; + if (idx >= Children.Count) + return; + GraphicObject c = Children [idx]; + if (!c.Visible) + continue; + //ensure Item are not realigned + c.HorizontalAlignment = HorizontalAlignment.Left; + c.VerticalAlignment = VerticalAlignment.Top; + c.Left = curX * (slotWidth + Spacing); + c.Top = curY * (slotHeight + Spacing); + c.Width = slotWidth; + c.Height = slotHeight; + } + } + } + + public override void RegisterForLayouting (int layoutType) + { + base.RegisterForLayouting (layoutType); + + if ((layoutType & (int)LayoutingType.PositionChildren) > 0) + Interface.LayoutingQueue.Enqueue (LayoutingType.PositionChildren, this); + } + public override void UpdateLayout (LayoutingType layoutType) + { + if (layoutType == LayoutingType.PositionChildren) { + ComputeChildrenPositions (); + //if no layouting remains in queue for item, registre for redraw + if (Interface.LayoutingQueue.Where (lq => lq.GraphicObject == this).Count () <= 0 && bmp==null) + this.RegisterForRedraw (); + }else + base.UpdateLayout(layoutType); + } + #endregion + + + } +} diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index 034a2616..e03399e9 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -1,317 +1,317 @@ -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;
-
-namespace Crow
-{
- public class Group : GraphicObject, IXmlSerializable
- {
- #region CTOR
- public Group()
- : base()
- {
- }
- #endregion
-
- #region EVENT HANDLERS
- public event EventHandler<EventArgs> ChildrenCleared;
- #endregion
-
- internal int maxChildrenWidth = 0;
- internal int maxChildrenHeight = 0;
-
- bool _multiSelect = false;
- List<GraphicObject> children = new List<GraphicObject>();
-
- public GraphicObject activeWidget;
-
- public virtual List<GraphicObject> Children {
- get { return children; }
- set { children = value; }
- }
- [XmlAttributeAttribute()][DefaultValue(false)]
- public bool MultiSelect
- {
- get { return _multiSelect; }
- set { _multiSelect = value; }
- }
-
-
- public virtual T addChild<T>(T child)
- {
- GraphicObject g = child as GraphicObject;
- Children.Add(g);
- g.Parent = this as GraphicObject;
- g.RegisterForLayouting ((int)LayoutingType.Sizing);
- return (T)child;
- }
- public virtual void removeChild(GraphicObject child)
- {
- child.ClearBinding ();
- child.Parent = null;
- Children.Remove(child);
- this.RegisterForLayouting ((int)LayoutingType.Sizing);
- }
- public virtual void ClearChildren()
- {
- int lim = children.Count;
- for (int i = 0; i < lim; i++) {
- GraphicObject g = Children [0];
- g.ClearBinding ();
- g.Parent = null;
- Children.Remove(g);
- }
- this.RegisterForLayouting ((int)LayoutingType.Sizing);
- ChildrenCleared.Raise (this, new EventArgs ());
- }
- public void putWidgetOnTop(GraphicObject w)
- {
- if (Children.Contains(w))
- {
- Children.Remove(w);
- Children.Add(w);
- }
- }
- public void putWidgetOnBottom(GraphicObject w)
- {
- if (Children.Contains(w))
- {
- Children.Remove(w);
- Children.Insert(0, w);
- }
- }
-
- #region GraphicObject overrides
- [XmlIgnore]public override bool DrawingIsValid {
- get {
- if (!base.DrawingIsValid)
- return false;
- foreach (GraphicObject g in Children) {
- if (!g.DrawingIsValid)
- return false;
- }
- return true;
- }
- }
- public override void ResolveBindings ()
- {
- base.ResolveBindings ();
- foreach (GraphicObject w in Children)
- w.ResolveBindings ();
- }
- public override GraphicObject FindByName (string nameToFind)
- {
- if (Name == nameToFind)
- return this;
-
- foreach (GraphicObject w in Children) {
- GraphicObject r = w.FindByName (nameToFind);
- if (r != null)
- return r;
- }
- return null;
- }
- public override bool Contains (GraphicObject goToFind)
- {
- foreach (GraphicObject w in Children) {
- if (w == goToFind)
- return true;
- if (w.Contains (goToFind))
- return true;
- }
- return false;
- }
- protected override Size measureRawSize ()
- {
-// Size tmp = new Size ();
-//
-// foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) {
-// tmp.Width = Math.Max (tmp.Width, c.Slot.Right);
-// tmp.Height = Math.Max (tmp.Height, c.Slot.Bottom);
-// }
-//
-// tmp.Width += 2*Margin;
-// tmp.Height += 2*Margin;
-//
-// return tmp;
- return new Size(maxChildrenWidth + 2 * Margin, maxChildrenHeight + 2 * Margin);
- }
-
- public override void OnLayoutChanges (LayoutingType layoutType)
- {
- base.OnLayoutChanges (layoutType);
-
- GenericStack gs = this as GenericStack;
- //position smaller objects in group when group size is fit
- switch (layoutType) {
- case LayoutingType.Width:
- if (gs != null) {
- if (gs.Orientation == Orientation.Horizontal) {
- this.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- break;
- }
- }
- foreach (GraphicObject c in Children.Where(ch => ch.Visible)) {
- if (c.getBounds ().Width == 0)
- c.RegisterForLayouting ((int)LayoutingType.Width);
- else
- c.RegisterForLayouting ((int)LayoutingType.X);
- }
- break;
- case LayoutingType.Height:
- if (gs != null) {
- if (gs.Orientation == Orientation.Vertical) {
- this.RegisterForLayouting ((int)LayoutingType.PositionChildren);
- break;
- }
- }
- foreach (GraphicObject c in Children.Where(ch => ch.Visible)) {
- if (c.getBounds ().Height == 0)
- c.RegisterForLayouting ((int)LayoutingType.Height);
- else
- c.RegisterForLayouting ((int)LayoutingType.Y);
- }
- break;
- }
- }
-
- public override Rectangle ContextCoordinates(Rectangle r){
- return r + ClientRectangle.Position;
- }
-
- protected override void onDraw (Context gr)
- {
- Rectangle rBack = new Rectangle (Slot.Size);
- gr.SetSourceColor(Background);
- CairoHelpers.CairoRectangle(gr,rBack,CornerRadius);
- gr.Fill ();
-
- foreach (GraphicObject g in Children) {
- g.Paint (ref gr);
- }
- }
-
- public override void Paint(ref Context ctx, Rectangles clip = null)
- {
- if ( !Visible )
- return;
-
- if (bmp == null)
- UpdateGraphic ();
- else {
- if (clip != null)
- clip.Rebase (this);
- else {
- clip = new Rectangles ();
- //TODO:added lately slot to empty clip,
- //should rework this precise case causing expandable not
- //to show image changes
- clip.AddRectangle (ContextCoordinates (Slot.Size));
- }
-
- if (!DrawingIsValid || clip != null) {//false when 1 child has changed
- //child having their content changed has to be repainted
- //and those with slot intersecting clip rectangle have also to be repainted
-
- using (ImageSurface cache =
- new ImageSurface (bmp, Format.Argb32, Slot.Width, Slot.Height, Slot.Width * 4)) {
- Context gr = new Context (cache);
- clip.clearAndClip (gr);
-
- Rectangle rBack = Slot.Size;
- gr.SetSourceColor(Background);
- CairoHelpers.CairoRectangle(gr,rBack,CornerRadius);
- gr.Fill ();
- #if DEBUG_CLIP_RECTANGLE
- clip.stroke (gr, Color.Amaranth.AdjustAlpha (0.8));
- #endif
- 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);
- }
-
- gr.Dispose ();
- }
- }
- }
-
- base.Paint (ref ctx, clip);
- }
- #endregion
-
-
- #region Mouse handling
- public override void checkHoverWidget (OpenTK.Input.MouseMoveEventArgs e)
- {
- if (HostContainer.hoverWidget != this) {
- HostContainer.hoverWidget = this;
- onMouseEnter (this, e);
- }
- foreach (GraphicObject g in Children)
- {
- if (g.MouseIsIn(e.Position))
- {
- g.checkHoverWidget (e);
- return;
- }
- }
- base.checkHoverWidget (e);
- }
- #endregion
-
- #region IXmlSerializable
-
- public override System.Xml.Schema.XmlSchema GetSchema()
- {
- return null;
- }
- public override void ReadXml(System.Xml.XmlReader reader)
- {
- base.ReadXml(reader);
-
- using (System.Xml.XmlReader subTree = reader.ReadSubtree())
- {
- subTree.Read();
-
- while (!subTree.EOF)
- {
- subTree.Read();
-
- if (!subTree.IsStartElement())
- break;
-
- Type t = Type.GetType("Crow." + subTree.Name);
- GraphicObject go = (GraphicObject)Activator.CreateInstance(t);
- (go as IXmlSerializable).ReadXml(subTree);
- addChild(go);
- }
- }
- }
- public override void WriteXml(System.Xml.XmlWriter writer)
- {
- base.WriteXml(writer);
-
- foreach (GraphicObject go in Children)
- {
- writer.WriteStartElement(go.GetType().Name);
- (go as IXmlSerializable).WriteXml(writer);
- writer.WriteEndElement();
- }
- }
-
- #endregion
-
- public override void ClearBinding(){
- foreach (GraphicObject c in children)
- c.ClearBinding ();
- base.ClearBinding ();
- }
- }
-}
+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; + +namespace Crow +{ + public class Group : GraphicObject, IXmlSerializable + { + #region CTOR + public Group() + : base() + { + } + #endregion + + #region EVENT HANDLERS + public event EventHandler<EventArgs> ChildrenCleared; + #endregion + + internal int maxChildrenWidth = 0; + internal int maxChildrenHeight = 0; + + bool _multiSelect = false; + List<GraphicObject> children = new List<GraphicObject>(); + + public GraphicObject activeWidget; + + public virtual List<GraphicObject> Children { + get { return children; } + set { children = value; } + } + [XmlAttributeAttribute()][DefaultValue(false)] + public bool MultiSelect + { + get { return _multiSelect; } + set { _multiSelect = value; } + } + + + public virtual T addChild<T>(T child) + { + GraphicObject g = child as GraphicObject; + Children.Add(g); + g.Parent = this as GraphicObject; + g.RegisterForLayouting ((int)LayoutingType.Sizing); + return (T)child; + } + public virtual void removeChild(GraphicObject child) + { + child.ClearBinding (); + child.Parent = null; + Children.Remove(child); + this.RegisterForLayouting ((int)LayoutingType.Sizing); + } + public virtual void ClearChildren() + { + int lim = children.Count; + for (int i = 0; i < lim; i++) { + GraphicObject g = Children [0]; + g.ClearBinding (); + g.Parent = null; + Children.Remove(g); + } + this.RegisterForLayouting ((int)LayoutingType.Sizing); + ChildrenCleared.Raise (this, new EventArgs ()); + } + public void putWidgetOnTop(GraphicObject w) + { + if (Children.Contains(w)) + { + Children.Remove(w); + Children.Add(w); + } + } + public void putWidgetOnBottom(GraphicObject w) + { + if (Children.Contains(w)) + { + Children.Remove(w); + Children.Insert(0, w); + } + } + + #region GraphicObject overrides + [XmlIgnore]public override bool DrawingIsValid { + get { + if (!base.DrawingIsValid) + return false; + foreach (GraphicObject g in Children) { + if (!g.DrawingIsValid) + return false; + } + return true; + } + } + public override void ResolveBindings () + { + base.ResolveBindings (); + foreach (GraphicObject w in Children) + w.ResolveBindings (); + } + public override GraphicObject FindByName (string nameToFind) + { + if (Name == nameToFind) + return this; + + foreach (GraphicObject w in Children) { + GraphicObject r = w.FindByName (nameToFind); + if (r != null) + return r; + } + return null; + } + public override bool Contains (GraphicObject goToFind) + { + foreach (GraphicObject w in Children) { + if (w == goToFind) + return true; + if (w.Contains (goToFind)) + return true; + } + return false; + } + protected override Size measureRawSize () + { +// Size tmp = new Size (); +// +// foreach (GraphicObject c in Children.Where(ch=>ch.Visible)) { +// tmp.Width = Math.Max (tmp.Width, c.Slot.Right); +// tmp.Height = Math.Max (tmp.Height, c.Slot.Bottom); +// } +// +// tmp.Width += 2*Margin; +// tmp.Height += 2*Margin; +// +// return tmp; + return new Size(maxChildrenWidth + 2 * Margin, maxChildrenHeight + 2 * Margin); + } + + public override void OnLayoutChanges (LayoutingType layoutType) + { + base.OnLayoutChanges (layoutType); + + GenericStack gs = this as GenericStack; + //position smaller objects in group when group size is fit + switch (layoutType) { + case LayoutingType.Width: + if (gs != null) { + if (gs.Orientation == Orientation.Horizontal) { + this.RegisterForLayouting ((int)LayoutingType.PositionChildren); + break; + } + } + foreach (GraphicObject c in Children.Where(ch => ch.Visible)) { + if (c.getBounds ().Width == 0) + c.RegisterForLayouting ((int)LayoutingType.Width); + else + c.RegisterForLayouting ((int)LayoutingType.X); + } + break; + case LayoutingType.Height: + if (gs != null) { + if (gs.Orientation == Orientation.Vertical) { + this.RegisterForLayouting ((int)LayoutingType.PositionChildren); + break; + } + } + foreach (GraphicObject c in Children.Where(ch => ch.Visible)) { + if (c.getBounds ().Height == 0) + c.RegisterForLayouting ((int)LayoutingType.Height); + else + c.RegisterForLayouting ((int)LayoutingType.Y); + } + break; + } + } + + public override Rectangle ContextCoordinates(Rectangle r){ + return r + ClientRectangle.Position; + } + + protected override void onDraw (Context gr) + { + Rectangle rBack = new Rectangle (Slot.Size); + gr.SetSourceColor(Background); + CairoHelpers.CairoRectangle(gr,rBack,CornerRadius); + gr.Fill (); + + foreach (GraphicObject g in Children) { + g.Paint (ref gr); + } + } + + public override void Paint(ref Context ctx, Rectangles clip = null) + { + if ( !Visible ) + return; + + if (bmp == null) + UpdateGraphic (); + else { + if (clip != null) + clip.Rebase (this); + else { + clip = new Rectangles (); + //TODO:added lately slot to empty clip, + //should rework this precise case causing expandable not + //to show image changes + clip.AddRectangle (ContextCoordinates (Slot.Size)); + } + + if (!DrawingIsValid || clip != null) {//false when 1 child has changed + //child having their content changed has to be repainted + //and those with slot intersecting clip rectangle have also to be repainted + + using (ImageSurface cache = + new ImageSurface (bmp, Format.Argb32, Slot.Width, Slot.Height, Slot.Width * 4)) { + Context gr = new Context (cache); + clip.clearAndClip (gr); + + Rectangle rBack = Slot.Size; + gr.SetSourceColor(Background); + CairoHelpers.CairoRectangle(gr,rBack,CornerRadius); + gr.Fill (); + #if DEBUG_CLIP_RECTANGLE + clip.stroke (gr, Color.Amaranth.AdjustAlpha (0.8)); + #endif + 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); + } + + gr.Dispose (); + } + } + } + + base.Paint (ref ctx, clip); + } + #endregion + + + #region Mouse handling + public override void checkHoverWidget (OpenTK.Input.MouseMoveEventArgs e) + { + if (HostContainer.hoverWidget != this) { + HostContainer.hoverWidget = this; + onMouseEnter (this, e); + } + foreach (GraphicObject g in Children) + { + if (g.MouseIsIn(e.Position)) + { + g.checkHoverWidget (e); + return; + } + } + base.checkHoverWidget (e); + } + #endregion + + #region IXmlSerializable + + public override System.Xml.Schema.XmlSchema GetSchema() + { + return null; + } + public override void ReadXml(System.Xml.XmlReader reader) + { + base.ReadXml(reader); + + using (System.Xml.XmlReader subTree = reader.ReadSubtree()) + { + subTree.Read(); + + while (!subTree.EOF) + { + subTree.Read(); + + if (!subTree.IsStartElement()) + break; + + Type t = Type.GetType("Crow." + subTree.Name); + GraphicObject go = (GraphicObject)Activator.CreateInstance(t); + (go as IXmlSerializable).ReadXml(subTree); + addChild(go); + } + } + } + public override void WriteXml(System.Xml.XmlWriter writer) + { + base.WriteXml(writer); + + foreach (GraphicObject go in Children) + { + writer.WriteStartElement(go.GetType().Name); + (go as IXmlSerializable).WriteXml(writer); + writer.WriteEndElement(); + } + } + + #endregion + + public override void ClearBinding(){ + foreach (GraphicObject c in children) + c.ClearBinding (); + base.ClearBinding (); + } + } +} diff --git a/src/GraphicObjects/GroupBox.cs b/src/GraphicObjects/GroupBox.cs index 81bac117..9206792a 100644 --- a/src/GraphicObjects/GroupBox.cs +++ b/src/GraphicObjects/GroupBox.cs @@ -1,68 +1,68 @@ -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
-{
- [DefaultTemplate("#Crow.Templates.GroupBox.goml")]
- public class GroupBox : TemplatedContainer
- {
- string caption;
- Container _contentContainer;
-
- #region CTOR
- public GroupBox() : base(){}
- #endregion
-
- #region Template overrides
- public override GraphicObject Content {
- get {
- return _contentContainer == null ? null : _contentContainer.Child;
- }
- set {
- _contentContainer.SetChild(value);
- }
- }
- protected override void loadTemplate(GraphicObject template = null)
- {
- base.loadTemplate (template);
-
- _contentContainer = this.child.FindByName ("Content") as Container;
- }
- #endregion
-
- #region GraphicObject overrides
- [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to true
- public override bool Focusable
- {
- get { return base.Focusable; }
- set { base.Focusable = value; }
- }
- #endregion
-
- [XmlAttributeAttribute()][DefaultValue("Groupbox")]
- public string Caption {
- get { return caption; }
- set {
- if (caption == value)
- return;
- caption = value;
- NotifyValueChanged ("Caption", caption);
- }
- }
- }
-}
+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 +{ + [DefaultTemplate("#Crow.Templates.GroupBox.goml")] + public class GroupBox : TemplatedContainer + { + string caption; + Container _contentContainer; + + #region CTOR + public GroupBox() : base(){} + #endregion + + #region Template overrides + public override GraphicObject Content { + get { + return _contentContainer == null ? null : _contentContainer.Child; + } + set { + _contentContainer.SetChild(value); + } + } + protected override void loadTemplate(GraphicObject template = null) + { + base.loadTemplate (template); + + _contentContainer = this.child.FindByName ("Content") as Container; + } + #endregion + + #region GraphicObject overrides + [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to true + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + #endregion + + [XmlAttributeAttribute()][DefaultValue("Groupbox")] + public string Caption { + get { return caption; } + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + } +} diff --git a/src/GraphicObjects/HorizontalStack.cs b/src/GraphicObjects/HorizontalStack.cs index 21991a9a..30fded86 100644 --- a/src/GraphicObjects/HorizontalStack.cs +++ b/src/GraphicObjects/HorizontalStack.cs @@ -1,23 +1,23 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml.Serialization;
-
-namespace Crow
-{
- public class HorizontalStack : GenericStack
- {
- public HorizontalStack()
- : base()
- {
- Orientation = Crow.Orientation.Horizontal;
- }
-
- [XmlIgnore]
- public override Orientation Orientation
- {
- get { return Orientation.Horizontal; }
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; + +namespace Crow +{ + public class HorizontalStack : GenericStack + { + public HorizontalStack() + : base() + { + Orientation = Crow.Orientation.Horizontal; + } + + [XmlIgnore] + public override Orientation Orientation + { + get { return Orientation.Horizontal; } + } + } +} diff --git a/src/GraphicObjects/Image.cs b/src/GraphicObjects/Image.cs index e7f75fe8..b8260c55 100644 --- a/src/GraphicObjects/Image.cs +++ b/src/GraphicObjects/Image.cs @@ -1,115 +1,115 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Cairo;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using System.Diagnostics;
-
-namespace Crow
-{
- public class Image : GraphicObject
- {
- Picture _pic;
- string _svgSub;
- bool scaled;
- [XmlAttributeAttribute()][DefaultValue(true)]
- public virtual bool Scaled {
- get { return scaled; }
- set {
- if (scaled == value)
- return;
- scaled = value;
- NotifyValueChanged ("Scaled", scaled);
- if (_pic == null)
- return;
- _pic.Scaled = scaled;
- registerForGraphicUpdate ();
- }
- }
- bool keepProps;
- [XmlAttributeAttribute()][DefaultValue(true)]
- public virtual bool KeepProportions {
- get { return keepProps; }
- set {
- if (keepProps == value)
- return;
- keepProps = value;
- NotifyValueChanged ("KeepProportions", keepProps);
- if (_pic == null)
- return;
- _pic.KeepProportions = keepProps;
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute("Path")]
- public string Path {
- get { return _pic == null ? null : _pic.Path; }
- set {
- try {
- if (string.IsNullOrEmpty(value)){
- _pic = null;
- return;
- }
- LoadImage (value);
- _pic.Scaled = scaled;
- _pic.KeepProportions = keepProps;
- } catch (Exception ex) {
- Debug.WriteLine (ex.Message);
- _pic = null;
- }
- }
- }
-
- [XmlAttributeAttribute()][DefaultValue(null)]
- public string SvgSub {
- get { return _svgSub; }
- set {
- _svgSub = value;
- registerForGraphicUpdate ();
- }
- }
-
- #region CTOR
- public Image () : base()
- {
- }
- #endregion
-
- #region Image Loading
- public void LoadImage (string path)
- {
-
- if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture))
- _pic = new SvgPicture ();
- else
- _pic = new BmpPicture ();
-
- _pic.LoadImage (path);
- registerForGraphicUpdate ();
- }
- #endregion
-
- #region GraphicObject overrides
- protected override Size measureRawSize ()
- {
-// if (_pic == null)
-// _pic = "#Crow.Images.Icons.IconAlerte.svg";
-
- return _pic.Dimensions + Margin * 2;
- }
- protected override void onDraw (Context gr)
- {
- base.onDraw (gr);
-
- if (_pic == null)
- return;
-
- _pic.Paint (gr, ClientRectangle, _svgSub);
- }
- #endregion
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Cairo; +using System.IO; +using System.Runtime.InteropServices; +using System.Xml.Serialization; +using System.ComponentModel; +using System.Diagnostics; + +namespace Crow +{ + public class Image : GraphicObject + { + Picture _pic; + string _svgSub; + bool scaled; + [XmlAttributeAttribute()][DefaultValue(true)] + public virtual bool Scaled { + get { return scaled; } + set { + if (scaled == value) + return; + scaled = value; + NotifyValueChanged ("Scaled", scaled); + if (_pic == null) + return; + _pic.Scaled = scaled; + registerForGraphicUpdate (); + } + } + bool keepProps; + [XmlAttributeAttribute()][DefaultValue(true)] + public virtual bool KeepProportions { + get { return keepProps; } + set { + if (keepProps == value) + return; + keepProps = value; + NotifyValueChanged ("KeepProportions", keepProps); + if (_pic == null) + return; + _pic.KeepProportions = keepProps; + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute("Path")] + public string Path { + get { return _pic == null ? null : _pic.Path; } + set { + try { + if (string.IsNullOrEmpty(value)){ + _pic = null; + return; + } + LoadImage (value); + _pic.Scaled = scaled; + _pic.KeepProportions = keepProps; + } catch (Exception ex) { + Debug.WriteLine (ex.Message); + _pic = null; + } + } + } + + [XmlAttributeAttribute()][DefaultValue(null)] + public string SvgSub { + get { return _svgSub; } + set { + _svgSub = value; + registerForGraphicUpdate (); + } + } + + #region CTOR + public Image () : base() + { + } + #endregion + + #region Image Loading + public void LoadImage (string path) + { + + if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture)) + _pic = new SvgPicture (); + else + _pic = new BmpPicture (); + + _pic.LoadImage (path); + registerForGraphicUpdate (); + } + #endregion + + #region GraphicObject overrides + protected override Size measureRawSize () + { +// if (_pic == null) +// _pic = "#Crow.Images.Icons.IconAlerte.svg"; + + return _pic.Dimensions + Margin * 2; + } + protected override void onDraw (Context gr) + { + base.onDraw (gr); + + if (_pic == null) + return; + + _pic.Paint (gr, ClientRectangle, _svgSub); + } + #endregion + } +} diff --git a/src/GraphicObjects/Label.cs b/src/GraphicObjects/Label.cs index 1af9e04b..0b93924a 100644 --- a/src/GraphicObjects/Label.cs +++ b/src/GraphicObjects/Label.cs @@ -1,679 +1,679 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Cairo;
-using System.Text.RegularExpressions;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using OpenTK.Input;
-
-namespace Crow
-{
- [Serializable]
- public class Label : GraphicObject
- {
- #region CTOR
- public Label()
- {
-
- }
- public Label(string _text)
- : base()
- {
- Text = _text;
- }
- #endregion
-
- //TODO:change protected to private
-
- #region private and protected fields
- string _text = "label";
- Alignment _textAlignment = Alignment.LeftCenter;
- bool _multiline = false;
- Color selColor;
- Color selFontColor;
- Point mouseLocalPos = -1;//mouse coord in widget space, filled only when clicked
- int _currentCol; //0 based cursor position in string
- int _currentLine;
- Point _selBegin = -1; //selection start (row,column)
- Point _selRelease = -1; //selection end (row,column)
- double textCursorPos; //cursor position in cairo units in widget client coord.
- double SelStartCursorPos = -1;
- double SelEndCursorPos = -1;
- bool SelectionInProgress = false;
-
- protected Rectangle rText;
- protected float widthRatio = 1f;
- protected float heightRatio = 1f;
- protected FontExtents fe;
- protected TextExtents te;
- #endregion
-
- [XmlAttributeAttribute()][DefaultValue("SteelBlue")]
- public virtual Color SelectionBackground {
- get { return selColor; }
- set {
- if (value == selColor)
- return;
- selColor = value;
- NotifyValueChanged ("SelectionBackground", selColor);
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue("White")]
- public virtual Color SelectionForeground {
- get { return selFontColor; }
- set {
- if (value == selFontColor)
- return;
- selFontColor = value;
- NotifyValueChanged ("SelectionForeground", selFontColor);
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(Alignment.LeftCenter)]
- public Alignment TextAlignment
- {
- get { return _textAlignment; }
- set {
- if (value == _textAlignment)
- return;
- _textAlignment = value;
- registerForGraphicUpdate ();
- NotifyValueChanged ("TextAlignment", _textAlignment);
- }
- }
- [XmlAttributeAttribute()][DefaultValue("label")]
- public string Text
- {
- get {
- return lines == null ?
- _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j);
- }
- set
- {
- if (_text == value)
- return;
-
- _text = value;
-
- if (string.IsNullOrEmpty(_text))
- _text = "";
-
- lines = getLines;
-
- this.registerForGraphicUpdate ();
- this.RegisterForLayouting ((int)LayoutingType.Sizing);
- NotifyValueChanged ("Text", Text);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(false)]
- public bool Multiline
- {
- get { return _multiline; }
- set
- {
- if (value == _multiline)
- return;
- _multiline = value;
- NotifyValueChanged ("Multiline", _multiline);
- registerForGraphicUpdate();
- }
- }
- [XmlIgnore]public int CurrentColumn{
- get { return _currentCol; }
- set {
- if (value == _currentCol)
- return;
- if (value < 0)
- _currentCol = 0;
- else if (value > lines [_currentLine].Count ())
- _currentCol = lines [_currentLine].Count ();
- else
- _currentCol = value;
- NotifyValueChanged ("CurrentColumn", _currentCol);
- }
- }
- [XmlIgnore]public int CurrentLine{
- get { return _currentLine; }
- set {
- if (value == _currentLine)
- return;
- if (value > lines.Count)
- _currentLine = lines.Count;
- else if (value < 0)
- _currentLine = 0;
- else
- _currentLine = value;
- NotifyValueChanged ("CurrentLine", _currentLine);
- }
- }
- [XmlIgnore]public Point SelBegin {
- get {
- return _selBegin;
- }
- set {
- if (value == _selBegin)
- return;
- _selBegin = value;
- NotifyValueChanged ("SelectedText", SelectedText);
- }
- }
- [XmlIgnore]public Point SelRelease {
- get {
- return _selRelease;
- }
- set {
- if (value == _selRelease)
- return;
- _selRelease = value;
- NotifyValueChanged ("SelectedText", SelectedText);
- }
- }
-
- [XmlIgnore]protected Point selectionStart //ordered selection start and end positions
- {
- get {
- return SelRelease < 0 || SelBegin.Y < SelRelease.Y ? SelBegin :
- SelBegin.Y > SelRelease.Y ? SelRelease :
- SelBegin.X < SelRelease.X ? SelBegin : SelRelease;
- }
- }
- [XmlIgnore]public Point selectionEnd
- {
- get {
- return SelRelease < 0 || SelBegin.Y > SelRelease.Y ? SelBegin :
- SelBegin.Y < SelRelease.Y ? SelRelease :
- SelBegin.X > SelRelease.X ? SelBegin : SelRelease;
- }
- }
- [XmlIgnore]public string SelectedText
- {
- get {
-
- if (SelRelease < 0 || SelBegin < 0)
- return "";
- if (selectionStart.Y == selectionEnd.Y)
- return lines [selectionStart.Y].Substring (selectionStart.X, selectionEnd.X - selectionStart.X);
- string tmp = "";
- tmp = lines [selectionStart.Y].Substring (selectionStart.X);
- for (int l = selectionStart.Y + 1; l < selectionEnd.Y; l++) {
- tmp += Interface.LineBreak + lines [l];
- }
- tmp += Interface.LineBreak + lines [selectionEnd.Y].Substring (0, selectionEnd.X);
- return tmp;
- }
- }
- [XmlIgnore]public bool selectionIsEmpty
- { get { return SelRelease < 0; } }
-
- List<string> lines;
- List<string> getLines {
- get {
- return _multiline ?
- Regex.Split (_text, "\r\n|\r|\n|" + @"\\n").ToList() :
- new List<string>(new string[] { _text });
- }
- }
-
- public void DeleteChar()
- {
- if (selectionIsEmpty) {
- if (CurrentColumn == 0) {
- if (CurrentLine == 0)
- return;
- CurrentLine--;
- CurrentColumn = lines [CurrentLine].Count ();
- lines [CurrentLine] += lines [CurrentLine + 1];
- lines.RemoveAt (CurrentLine + 1);
- return;
- }
- CurrentColumn--;
- lines [CurrentLine] = lines [CurrentLine].Remove (CurrentColumn, 1);
- } else {
- Debug.WriteLine (selectionEnd.ToString());
- int linesToRemove = selectionEnd.Y - selectionStart.Y;
- int l = selectionStart.Y;
-
- if (linesToRemove > 0) {
- lines [l] = lines [l].Remove (selectionStart.X, lines [l].Length - selectionStart.X) +
- lines [selectionEnd.Y].Substring (selectionEnd.X, lines [selectionEnd.Y].Length - selectionEnd.X);
- l++;
- for (int c = 0; c < linesToRemove-1; c++)
- lines.RemoveAt (l);
- CurrentColumn = selectionStart.X;
- CurrentLine = selectionStart.Y;
- } else
- lines [l] = lines [l].Remove (selectionStart.X, selectionEnd.X - selectionStart.X);
- CurrentColumn = selectionStart.X;
- SelBegin = -1;
- SelRelease = -1;
- }
- }
- /// <summary>
- /// Insert new string at caret position, should be sure no line break is inside.
- /// </summary>
- /// <param name="str">String.</param>
- protected void Insert(string str)
- {
- lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, str);
- CurrentColumn += str.Length;
- }
-
- #region GraphicObject overrides
- [XmlAttributeAttribute()][DefaultValue(-1)]
- public override int Width {
- get { return base.Width; }
- set { base.Width = value; }
- }
- [XmlAttributeAttribute()][DefaultValue(-1)]
- public override int Height {
- get { return base.Height; }
- set { base.Height = value; }
- }
-
- protected override Size measureRawSize()
- {
- Size size;
-
- 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 ();
-
- gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
- gr.SetFontSize (Font.Size);
-
- te = new TextExtents();
-
- foreach (string s in lines) {
- string l = s.Replace("\t", new String (' ', Interface.TabSize));
-
-#if _WIN32 || _WIN64
- TextExtents tmp = gr.TextExtents(str.ToUtf8());
-#elif __linux__
- TextExtents tmp = gr.TextExtents (l);
-#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 size;;
- }
- protected override void onDraw (Context gr)
- {
- base.onDraw (gr);
-
- gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
- gr.SetFontSize (Font.Size);
-
- gr.Antialias = Antialias.Subpixel;
- //gr.FontOptions.Antialias = Antialias.Subpixel;
- //gr.FontOptions.HintMetrics = HintMetrics.On;
-
- rText = new Rectangle(measureRawSize());
- rText.Width -= 2 * Margin;
- rText.Height -= 2 * Margin;
-
- widthRatio = 1f;
- heightRatio = 1f;
-
- Rectangle cb = ClientRectangle;
-
- //ignore text alignment if size to content = true
- if (Bounds.Size < 0)
- {
- rText.X = cb.X;
- rText.Y = cb.Y;
- }else{
- switch (TextAlignment)
- {
- case Alignment.None:
- break;
- case Alignment.TopLeft: //ok
- rText.X = cb.X;
- rText.Y = cb.Y;
- break;
- case Alignment.TopCenter: //ok
- rText.Y = cb.Y;
- rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
- break;
- case Alignment.TopRight: //ok
- rText.X = cb.Right - rText.Width;
- rText.Y = cb.Y;
- break;
- case Alignment.TopStretch://ok
- heightRatio = widthRatio = (float)cb.Width / rText.Width;
- rText.X = cb.X;
- rText.Y = cb.Y;
- rText.Width = cb.Width;
- rText.Height = (int)(rText.Height * heightRatio);
- break;
- case Alignment.LeftCenter://ok
- rText.X = cb.X;
- rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
- break;
- case Alignment.LeftStretch://ok
- heightRatio = widthRatio = (float)cb.Height / rText.Height;
- rText.X = cb.X;
- rText.Y = cb.Y;
- rText.Height = cb.Height;
- rText.Width = (int)(widthRatio * cb.Width);
- break;
- case Alignment.RightCenter://ok
- rText.X = cb.X + cb.Width - rText.Width;
- rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
- break;
- case Alignment.RightStretch://ok
- heightRatio = widthRatio = (float)cb.Height / rText.Height;
- rText.Height = cb.Height;
- rText.Width = (int)(widthRatio * rText.Width);
- rText.X = cb.Right - rText.Width;
- rText.Y = cb.Y;
- break;
- case Alignment.BottomCenter://ok
- rText.X = cb.Width / 2 - rText.Width / 2;
- rText.Y = cb.Height - rText.Height;
- break;
- case Alignment.BottomStretch://ok
- heightRatio = widthRatio = (float)cb.Width / rText.Width;
- rText.Width = cb.Width;
- rText.Height = (int)(rText.Height * heightRatio);
- rText.Y = cb.Bottom - rText.Height;
- rText.X = cb.X;
- break;
- case Alignment.BottomLeft://ok
- rText.X = cb.X;
- rText.Y = cb.Bottom - rText.Height;
- break;
- case Alignment.BottomRight://ok
- rText.Y = cb.Bottom - rText.Height;
- rText.X = cb.Right - rText.Width;
- break;
- case Alignment.Center://ok
- rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
- rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
- break;
- case Alignment.Fit://ok, peut être mieu aligné
- widthRatio = (float)cb.Width / rText.Width;
- heightRatio = (float)cb.Height / rText.Height;
- rText = cb;
- break;
- case Alignment.HorizontalStretch://ok
- heightRatio = widthRatio = (float)cb.Width / rText.Width;
- rText.Width = cb.Width;
- rText.Height = (int)(heightRatio * rText.Height);
- rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
- rText.X = cb.X;
- break;
- case Alignment.VerticalStretch://ok
- heightRatio = widthRatio = (float)cb.Height / rText.Height;
- rText.Height = cb.Height;
- rText.Width = (int)(widthRatio * rText.Width);
- rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
- rText.Y = cb.Y;
- break;
- default:
- break;
- }
- }
-
- gr.FontMatrix = new Matrix(widthRatio * Font.Size, 0, 0, heightRatio * Font.Size, 0, 0);
- fe = gr.FontExtents;
-
- #region draw text cursor
- if (mouseLocalPos >= 0)
- {
- computeTextCursor(gr);
-
- if (SelectionInProgress)
- {
- if (SelBegin < 0){
- SelBegin = new Point(CurrentColumn, CurrentLine);
- SelStartCursorPos = textCursorPos;
- SelRelease = -1;
- }else{
- SelRelease = new Point(CurrentColumn, CurrentLine);
- if (SelRelease == SelBegin)
- SelRelease = -1;
- else
- SelEndCursorPos = textCursorPos;
- }
- }
- }else
- computeTextCursorPosition(gr);
-
-
- #endregion
-
- //****** debug selection *************
-// if (SelRelease >= 0) {
-// gr.Color = Color.Green;
-// Rectangle R = new Rectangle (
-// rText.X + (int)SelEndCursorPos - 2,
-// rText.Y + (int)(SelRelease.Y * fe.Height),
-// 4,
-// (int)fe.Height);
-// gr.Rectangle (R);
-// gr.Fill ();
-// }
-// if (SelBegin >= 0) {
-// gr.Color = Color.UnmellowYellow;
-// Rectangle R = new Rectangle (
-// rText.X + (int)SelStartCursorPos - 2,
-// rText.Y + (int)(SelBegin.Y * fe.Height),
-// 4,
-// (int)fe.Height);
-// gr.Rectangle (R);
-// gr.Fill ();
-// }
- //*******************
-
- if (HasFocus )
- {
- gr.SetSourceColor(Foreground);
- gr.LineWidth = 1.5;
- gr.MoveTo(new PointD(textCursorPos + rText.X, rText.Y + CurrentLine * fe.Height));
- gr.LineTo(new PointD(textCursorPos + rText.X, rText.Y + (CurrentLine + 1) * fe.Height));
- gr.Stroke();
- }
-
- for (int i = 0; i < lines.Count; i++) {
- string l = lines [i].Replace ("\t", new String (' ', Interface.TabSize));
- int lineLength = (int)gr.TextExtents (l).XAdvance;
- Rectangle lineRect = new Rectangle (
- rText.X,
- rText.Y + (int)(i * fe.Height),
- lineLength,
- (int)fe.Height);
-
-// if (TextAlignment == Alignment.Center ||
-// TextAlignment == Alignment.TopCenter ||
-// TextAlignment == Alignment.BottomCenter)
-// lineRect.X += (rText.Width - lineLength) / 2;
-// else if (TextAlignment == Alignment.RightCenter ||
-// TextAlignment == Alignment.TopRight ||
-// TextAlignment == Alignment.BottomRight)
-// lineRect.X += (rText.Width - lineLength);
-
- if (SelRelease >= 0 && i >= selectionStart.Y && i <= selectionEnd.Y) {
- gr.SetSourceColor(selColor);
-
- Rectangle selRect = lineRect ;
-
- int cpStart = (int)SelStartCursorPos,
- cpEnd = (int)SelEndCursorPos;
-
- if (SelBegin.Y > SelRelease.Y) {
- cpStart = cpEnd;
- cpEnd = (int)SelStartCursorPos;
- }
-
- if (i == selectionStart.Y) {
- selRect.Width -= cpStart;
- selRect.Left += cpStart;
- }
- if (i == selectionEnd.Y)
- selRect.Width -= (lineLength - cpEnd);
-
- gr.Rectangle (selRect);
- gr.Fill ();
- }
-
- if (string.IsNullOrWhiteSpace (l))
- continue;
-
- gr.SetSourceColor(Foreground);
- gr.MoveTo (lineRect.X, rText.Y + fe.Ascent + fe.Height * i);
-
- #if _WIN32 || _WIN64
- gr.ShowText(l.ToUtf8());
- #elif __linux__
- gr.ShowText (l);
- #endif
- gr.Fill ();
- }
- }
- #endregion
-
- #region Mouse handling
- void updatemouseLocalPos(Point mpos){
- mouseLocalPos = mpos - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft;
- if (mouseLocalPos.X < 0)
- mouseLocalPos.X = 0;
- if (mouseLocalPos.Y < 0)
- mouseLocalPos.Y = 0;
- }
- public override void onFocused (object sender, EventArgs e)
- {
- base.onFocused (sender, e);
-
- SelBegin = new Point(0,0);
- SelRelease = new Point (lines.LastOrDefault ().Length, lines.Count-1);
- registerForGraphicUpdate ();
- }
- public override void onUnfocused (object sender, EventArgs e)
- {
- base.onUnfocused (sender, e);
-
- SelBegin = -1;
- SelRelease = -1;
- registerForGraphicUpdate ();
- }
- public override void onMouseMove (object sender, MouseMoveEventArgs e)
- {
- base.onMouseMove (sender, e);
-
- if (!(SelectionInProgress && HasFocus))
- return;
-
- updatemouseLocalPos (e.Position);
-
- registerForGraphicUpdate();
- }
- public override void onMouseDown (object sender, MouseButtonEventArgs e)
- {
- if (this.HasFocus){
- updatemouseLocalPos (e.Position);
- SelBegin = -1;
- SelRelease = -1;
- SelectionInProgress = true;
- }
-
- //done at the end to set 'hasFocus' value after testing it
- base.onMouseDown (sender, e);
-
- registerForGraphicUpdate();
- }
- public override void onMouseUp (object sender, MouseButtonEventArgs e)
- {
- base.onMouseUp (sender, e);
-
- if (!SelectionInProgress)
- return;
-
- updatemouseLocalPos (e.Position);
- SelectionInProgress = false;
- registerForGraphicUpdate ();
- }
- #endregion
- /// <summary>
- /// Update Current Column, line and TextCursorPos
- /// from mouseLocalPos
- /// </summary>
- void computeTextCursor(Context gr)
- {
- TextExtents te;
-
- double cPos = 0f;
-
- CurrentLine = (int)(mouseLocalPos.Y / fe.Height);
-
- //fix cu
- if (CurrentLine >= lines.Count)
- CurrentLine = lines.Count - 1;
-
- for (int i = 0; i < lines[CurrentLine].Length; i++)
- {
- string c = lines [CurrentLine].Substring (i, 1);
- if (c == "\t")
- c = new string (' ', Interface.TabSize);
-
- #if _WIN32 || _WIN64
- byte[] c = System.Text.UTF8Encoding.UTF8.GetBytes(Text.Substring(i, 1));
- te = gr.TextExtents(c);
- #elif __linux__
- te = gr.TextExtents(c);
- #endif
- double halfWidth = te.XAdvance / 2;
-
- if (mouseLocalPos.X <= cPos + halfWidth)
- {
- CurrentColumn = i;
- textCursorPos = cPos;
- mouseLocalPos = -1;
- return;
- }
-
- cPos += te.XAdvance;
- }
- CurrentColumn = lines[CurrentLine].Length;
- textCursorPos = cPos;
-
- //reset mouseLocalPos
- mouseLocalPos = -1;
- }
- /// <summary> Computes offsets in cairo units </summary>
- void computeTextCursorPosition(Context gr)
- {
- if (SelBegin >= 0)
- SelStartCursorPos = GetXFromTextPointer (gr, SelBegin);
- if (SelRelease >= 0)
- SelEndCursorPos = GetXFromTextPointer (gr, SelRelease);
- textCursorPos = GetXFromTextPointer (gr, new Point(CurrentColumn, CurrentLine));
- }
- /// <summary> Compute x offset in cairo unit from text position </summary>
- double GetXFromTextPointer(Context gr, Point pos)
- {
- try {
- string l = lines [pos.Y].Substring (0, pos.X).
- Replace ("\t", new String (' ', Interface.TabSize));
- return gr.TextExtents (l).XAdvance;
- } catch{
- return -1;
- }
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using Cairo; +using System.Text.RegularExpressions; +using System.Xml.Serialization; +using System.ComponentModel; +using OpenTK.Input; + +namespace Crow +{ + [Serializable] + public class Label : GraphicObject + { + #region CTOR + public Label() + { + + } + public Label(string _text) + : base() + { + Text = _text; + } + #endregion + + //TODO:change protected to private + + #region private and protected fields + string _text = "label"; + Alignment _textAlignment = Alignment.LeftCenter; + bool _multiline = false; + Color selColor; + Color selFontColor; + Point mouseLocalPos = -1;//mouse coord in widget space, filled only when clicked + int _currentCol; //0 based cursor position in string + int _currentLine; + Point _selBegin = -1; //selection start (row,column) + Point _selRelease = -1; //selection end (row,column) + double textCursorPos; //cursor position in cairo units in widget client coord. + double SelStartCursorPos = -1; + double SelEndCursorPos = -1; + bool SelectionInProgress = false; + + protected Rectangle rText; + protected float widthRatio = 1f; + protected float heightRatio = 1f; + protected FontExtents fe; + protected TextExtents te; + #endregion + + [XmlAttributeAttribute()][DefaultValue("SteelBlue")] + public virtual Color SelectionBackground { + get { return selColor; } + set { + if (value == selColor) + return; + selColor = value; + NotifyValueChanged ("SelectionBackground", selColor); + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue("White")] + public virtual Color SelectionForeground { + get { return selFontColor; } + set { + if (value == selFontColor) + return; + selFontColor = value; + NotifyValueChanged ("SelectionForeground", selFontColor); + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue(Alignment.LeftCenter)] + public Alignment TextAlignment + { + get { return _textAlignment; } + set { + if (value == _textAlignment) + return; + _textAlignment = value; + registerForGraphicUpdate (); + NotifyValueChanged ("TextAlignment", _textAlignment); + } + } + [XmlAttributeAttribute()][DefaultValue("label")] + public string Text + { + get { + return lines == null ? + _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j); + } + set + { + if (_text == value) + return; + + _text = value; + + if (string.IsNullOrEmpty(_text)) + _text = ""; + + lines = getLines; + + this.registerForGraphicUpdate (); + this.RegisterForLayouting ((int)LayoutingType.Sizing); + NotifyValueChanged ("Text", Text); + } + } + [XmlAttributeAttribute()][DefaultValue(false)] + public bool Multiline + { + get { return _multiline; } + set + { + if (value == _multiline) + return; + _multiline = value; + NotifyValueChanged ("Multiline", _multiline); + registerForGraphicUpdate(); + } + } + [XmlIgnore]public int CurrentColumn{ + get { return _currentCol; } + set { + if (value == _currentCol) + return; + if (value < 0) + _currentCol = 0; + else if (value > lines [_currentLine].Count ()) + _currentCol = lines [_currentLine].Count (); + else + _currentCol = value; + NotifyValueChanged ("CurrentColumn", _currentCol); + } + } + [XmlIgnore]public int CurrentLine{ + get { return _currentLine; } + set { + if (value == _currentLine) + return; + if (value > lines.Count) + _currentLine = lines.Count; + else if (value < 0) + _currentLine = 0; + else + _currentLine = value; + NotifyValueChanged ("CurrentLine", _currentLine); + } + } + [XmlIgnore]public Point SelBegin { + get { + return _selBegin; + } + set { + if (value == _selBegin) + return; + _selBegin = value; + NotifyValueChanged ("SelectedText", SelectedText); + } + } + [XmlIgnore]public Point SelRelease { + get { + return _selRelease; + } + set { + if (value == _selRelease) + return; + _selRelease = value; + NotifyValueChanged ("SelectedText", SelectedText); + } + } + + [XmlIgnore]protected Point selectionStart //ordered selection start and end positions + { + get { + return SelRelease < 0 || SelBegin.Y < SelRelease.Y ? SelBegin : + SelBegin.Y > SelRelease.Y ? SelRelease : + SelBegin.X < SelRelease.X ? SelBegin : SelRelease; + } + } + [XmlIgnore]public Point selectionEnd + { + get { + return SelRelease < 0 || SelBegin.Y > SelRelease.Y ? SelBegin : + SelBegin.Y < SelRelease.Y ? SelRelease : + SelBegin.X > SelRelease.X ? SelBegin : SelRelease; + } + } + [XmlIgnore]public string SelectedText + { + get { + + if (SelRelease < 0 || SelBegin < 0) + return ""; + if (selectionStart.Y == selectionEnd.Y) + return lines [selectionStart.Y].Substring (selectionStart.X, selectionEnd.X - selectionStart.X); + string tmp = ""; + tmp = lines [selectionStart.Y].Substring (selectionStart.X); + for (int l = selectionStart.Y + 1; l < selectionEnd.Y; l++) { + tmp += Interface.LineBreak + lines [l]; + } + tmp += Interface.LineBreak + lines [selectionEnd.Y].Substring (0, selectionEnd.X); + return tmp; + } + } + [XmlIgnore]public bool selectionIsEmpty + { get { return SelRelease < 0; } } + + List<string> lines; + List<string> getLines { + get { + return _multiline ? + Regex.Split (_text, "\r\n|\r|\n|" + @"\\n").ToList() : + new List<string>(new string[] { _text }); + } + } + + public void DeleteChar() + { + if (selectionIsEmpty) { + if (CurrentColumn == 0) { + if (CurrentLine == 0) + return; + CurrentLine--; + CurrentColumn = lines [CurrentLine].Count (); + lines [CurrentLine] += lines [CurrentLine + 1]; + lines.RemoveAt (CurrentLine + 1); + return; + } + CurrentColumn--; + lines [CurrentLine] = lines [CurrentLine].Remove (CurrentColumn, 1); + } else { + Debug.WriteLine (selectionEnd.ToString()); + int linesToRemove = selectionEnd.Y - selectionStart.Y; + int l = selectionStart.Y; + + if (linesToRemove > 0) { + lines [l] = lines [l].Remove (selectionStart.X, lines [l].Length - selectionStart.X) + + lines [selectionEnd.Y].Substring (selectionEnd.X, lines [selectionEnd.Y].Length - selectionEnd.X); + l++; + for (int c = 0; c < linesToRemove-1; c++) + lines.RemoveAt (l); + CurrentColumn = selectionStart.X; + CurrentLine = selectionStart.Y; + } else + lines [l] = lines [l].Remove (selectionStart.X, selectionEnd.X - selectionStart.X); + CurrentColumn = selectionStart.X; + SelBegin = -1; + SelRelease = -1; + } + } + /// <summary> + /// Insert new string at caret position, should be sure no line break is inside. + /// </summary> + /// <param name="str">String.</param> + protected void Insert(string str) + { + lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, str); + CurrentColumn += str.Length; + } + + #region GraphicObject overrides + [XmlAttributeAttribute()][DefaultValue(-1)] + public override int Width { + get { return base.Width; } + set { base.Width = value; } + } + [XmlAttributeAttribute()][DefaultValue(-1)] + public override int Height { + get { return base.Height; } + set { base.Height = value; } + } + + protected override Size measureRawSize() + { + Size size; + + 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 (); + + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + + te = new TextExtents(); + + foreach (string s in lines) { + string l = s.Replace("\t", new String (' ', Interface.TabSize)); + +#if _WIN32 || _WIN64 + TextExtents tmp = gr.TextExtents(str.ToUtf8()); +#elif __linux__ + TextExtents tmp = gr.TextExtents (l); +#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 size;; + } + protected override void onDraw (Context gr) + { + base.onDraw (gr); + + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + + gr.Antialias = Antialias.Subpixel; + //gr.FontOptions.Antialias = Antialias.Subpixel; + //gr.FontOptions.HintMetrics = HintMetrics.On; + + rText = new Rectangle(measureRawSize()); + rText.Width -= 2 * Margin; + rText.Height -= 2 * Margin; + + widthRatio = 1f; + heightRatio = 1f; + + Rectangle cb = ClientRectangle; + + //ignore text alignment if size to content = true + if (Bounds.Size < 0) + { + rText.X = cb.X; + rText.Y = cb.Y; + }else{ + switch (TextAlignment) + { + case Alignment.None: + break; + case Alignment.TopLeft: //ok + rText.X = cb.X; + rText.Y = cb.Y; + break; + case Alignment.TopCenter: //ok + rText.Y = cb.Y; + rText.X = cb.X + cb.Width / 2 - rText.Width / 2; + break; + case Alignment.TopRight: //ok + rText.X = cb.Right - rText.Width; + rText.Y = cb.Y; + break; + case Alignment.TopStretch://ok + heightRatio = widthRatio = (float)cb.Width / rText.Width; + rText.X = cb.X; + rText.Y = cb.Y; + rText.Width = cb.Width; + rText.Height = (int)(rText.Height * heightRatio); + break; + case Alignment.LeftCenter://ok + rText.X = cb.X; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + case Alignment.LeftStretch://ok + heightRatio = widthRatio = (float)cb.Height / rText.Height; + rText.X = cb.X; + rText.Y = cb.Y; + rText.Height = cb.Height; + rText.Width = (int)(widthRatio * cb.Width); + break; + case Alignment.RightCenter://ok + rText.X = cb.X + cb.Width - rText.Width; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + case Alignment.RightStretch://ok + heightRatio = widthRatio = (float)cb.Height / rText.Height; + rText.Height = cb.Height; + rText.Width = (int)(widthRatio * rText.Width); + rText.X = cb.Right - rText.Width; + rText.Y = cb.Y; + break; + case Alignment.BottomCenter://ok + rText.X = cb.Width / 2 - rText.Width / 2; + rText.Y = cb.Height - rText.Height; + break; + case Alignment.BottomStretch://ok + heightRatio = widthRatio = (float)cb.Width / rText.Width; + rText.Width = cb.Width; + rText.Height = (int)(rText.Height * heightRatio); + rText.Y = cb.Bottom - rText.Height; + rText.X = cb.X; + break; + case Alignment.BottomLeft://ok + rText.X = cb.X; + rText.Y = cb.Bottom - rText.Height; + break; + case Alignment.BottomRight://ok + rText.Y = cb.Bottom - rText.Height; + rText.X = cb.Right - rText.Width; + break; + case Alignment.Center://ok + rText.X = cb.X + cb.Width / 2 - rText.Width / 2; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + case Alignment.Fit://ok, peut être mieu aligné + widthRatio = (float)cb.Width / rText.Width; + heightRatio = (float)cb.Height / rText.Height; + rText = cb; + break; + case Alignment.HorizontalStretch://ok + heightRatio = widthRatio = (float)cb.Width / rText.Width; + rText.Width = cb.Width; + rText.Height = (int)(heightRatio * rText.Height); + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + rText.X = cb.X; + break; + case Alignment.VerticalStretch://ok + heightRatio = widthRatio = (float)cb.Height / rText.Height; + rText.Height = cb.Height; + rText.Width = (int)(widthRatio * rText.Width); + rText.X = cb.X + cb.Width / 2 - rText.Width / 2; + rText.Y = cb.Y; + break; + default: + break; + } + } + + gr.FontMatrix = new Matrix(widthRatio * Font.Size, 0, 0, heightRatio * Font.Size, 0, 0); + fe = gr.FontExtents; + + #region draw text cursor + if (mouseLocalPos >= 0) + { + computeTextCursor(gr); + + if (SelectionInProgress) + { + if (SelBegin < 0){ + SelBegin = new Point(CurrentColumn, CurrentLine); + SelStartCursorPos = textCursorPos; + SelRelease = -1; + }else{ + SelRelease = new Point(CurrentColumn, CurrentLine); + if (SelRelease == SelBegin) + SelRelease = -1; + else + SelEndCursorPos = textCursorPos; + } + } + }else + computeTextCursorPosition(gr); + + + #endregion + + //****** debug selection ************* +// if (SelRelease >= 0) { +// gr.Color = Color.Green; +// Rectangle R = new Rectangle ( +// rText.X + (int)SelEndCursorPos - 2, +// rText.Y + (int)(SelRelease.Y * fe.Height), +// 4, +// (int)fe.Height); +// gr.Rectangle (R); +// gr.Fill (); +// } +// if (SelBegin >= 0) { +// gr.Color = Color.UnmellowYellow; +// Rectangle R = new Rectangle ( +// rText.X + (int)SelStartCursorPos - 2, +// rText.Y + (int)(SelBegin.Y * fe.Height), +// 4, +// (int)fe.Height); +// gr.Rectangle (R); +// gr.Fill (); +// } + //******************* + + if (HasFocus ) + { + gr.SetSourceColor(Foreground); + gr.LineWidth = 1.5; + gr.MoveTo(new PointD(textCursorPos + rText.X, rText.Y + CurrentLine * fe.Height)); + gr.LineTo(new PointD(textCursorPos + rText.X, rText.Y + (CurrentLine + 1) * fe.Height)); + gr.Stroke(); + } + + for (int i = 0; i < lines.Count; i++) { + string l = lines [i].Replace ("\t", new String (' ', Interface.TabSize)); + int lineLength = (int)gr.TextExtents (l).XAdvance; + Rectangle lineRect = new Rectangle ( + rText.X, + rText.Y + (int)(i * fe.Height), + lineLength, + (int)fe.Height); + +// if (TextAlignment == Alignment.Center || +// TextAlignment == Alignment.TopCenter || +// TextAlignment == Alignment.BottomCenter) +// lineRect.X += (rText.Width - lineLength) / 2; +// else if (TextAlignment == Alignment.RightCenter || +// TextAlignment == Alignment.TopRight || +// TextAlignment == Alignment.BottomRight) +// lineRect.X += (rText.Width - lineLength); + + if (SelRelease >= 0 && i >= selectionStart.Y && i <= selectionEnd.Y) { + gr.SetSourceColor(selColor); + + Rectangle selRect = lineRect ; + + int cpStart = (int)SelStartCursorPos, + cpEnd = (int)SelEndCursorPos; + + if (SelBegin.Y > SelRelease.Y) { + cpStart = cpEnd; + cpEnd = (int)SelStartCursorPos; + } + + if (i == selectionStart.Y) { + selRect.Width -= cpStart; + selRect.Left += cpStart; + } + if (i == selectionEnd.Y) + selRect.Width -= (lineLength - cpEnd); + + gr.Rectangle (selRect); + gr.Fill (); + } + + if (string.IsNullOrWhiteSpace (l)) + continue; + + gr.SetSourceColor(Foreground); + gr.MoveTo (lineRect.X, rText.Y + fe.Ascent + fe.Height * i); + + #if _WIN32 || _WIN64 + gr.ShowText(l.ToUtf8()); + #elif __linux__ + gr.ShowText (l); + #endif + gr.Fill (); + } + } + #endregion + + #region Mouse handling + void updatemouseLocalPos(Point mpos){ + mouseLocalPos = mpos - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft; + if (mouseLocalPos.X < 0) + mouseLocalPos.X = 0; + if (mouseLocalPos.Y < 0) + mouseLocalPos.Y = 0; + } + public override void onFocused (object sender, EventArgs e) + { + base.onFocused (sender, e); + + SelBegin = new Point(0,0); + SelRelease = new Point (lines.LastOrDefault ().Length, lines.Count-1); + registerForGraphicUpdate (); + } + public override void onUnfocused (object sender, EventArgs e) + { + base.onUnfocused (sender, e); + + SelBegin = -1; + SelRelease = -1; + registerForGraphicUpdate (); + } + public override void onMouseMove (object sender, MouseMoveEventArgs e) + { + base.onMouseMove (sender, e); + + if (!(SelectionInProgress && HasFocus)) + return; + + updatemouseLocalPos (e.Position); + + registerForGraphicUpdate(); + } + public override void onMouseDown (object sender, MouseButtonEventArgs e) + { + if (this.HasFocus){ + updatemouseLocalPos (e.Position); + SelBegin = -1; + SelRelease = -1; + SelectionInProgress = true; + } + + //done at the end to set 'hasFocus' value after testing it + base.onMouseDown (sender, e); + + registerForGraphicUpdate(); + } + public override void onMouseUp (object sender, MouseButtonEventArgs e) + { + base.onMouseUp (sender, e); + + if (!SelectionInProgress) + return; + + updatemouseLocalPos (e.Position); + SelectionInProgress = false; + registerForGraphicUpdate (); + } + #endregion + /// <summary> + /// Update Current Column, line and TextCursorPos + /// from mouseLocalPos + /// </summary> + void computeTextCursor(Context gr) + { + TextExtents te; + + double cPos = 0f; + + CurrentLine = (int)(mouseLocalPos.Y / fe.Height); + + //fix cu + if (CurrentLine >= lines.Count) + CurrentLine = lines.Count - 1; + + for (int i = 0; i < lines[CurrentLine].Length; i++) + { + string c = lines [CurrentLine].Substring (i, 1); + if (c == "\t") + c = new string (' ', Interface.TabSize); + + #if _WIN32 || _WIN64 + byte[] c = System.Text.UTF8Encoding.UTF8.GetBytes(Text.Substring(i, 1)); + te = gr.TextExtents(c); + #elif __linux__ + te = gr.TextExtents(c); + #endif + double halfWidth = te.XAdvance / 2; + + if (mouseLocalPos.X <= cPos + halfWidth) + { + CurrentColumn = i; + textCursorPos = cPos; + mouseLocalPos = -1; + return; + } + + cPos += te.XAdvance; + } + CurrentColumn = lines[CurrentLine].Length; + textCursorPos = cPos; + + //reset mouseLocalPos + mouseLocalPos = -1; + } + /// <summary> Computes offsets in cairo units </summary> + void computeTextCursorPosition(Context gr) + { + if (SelBegin >= 0) + SelStartCursorPos = GetXFromTextPointer (gr, SelBegin); + if (SelRelease >= 0) + SelEndCursorPos = GetXFromTextPointer (gr, SelRelease); + textCursorPos = GetXFromTextPointer (gr, new Point(CurrentColumn, CurrentLine)); + } + /// <summary> Compute x offset in cairo unit from text position </summary> + double GetXFromTextPointer(Context gr, Point pos) + { + try { + string l = lines [pos.Y].Substring (0, pos.X). + Replace ("\t", new String (' ', Interface.TabSize)); + return gr.TextExtents (l).XAdvance; + } catch{ + return -1; + } + } + } +} diff --git a/src/GraphicObjects/Popper.cs b/src/GraphicObjects/Popper.cs index 2ed1c06f..a7e1290c 100644 --- a/src/GraphicObjects/Popper.cs +++ b/src/GraphicObjects/Popper.cs @@ -1,188 +1,188 @@ -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
-{
- [DefaultTemplate("#Crow.Templates.Popper.goml")]
- public class Popper : TemplatedContainer
- {
- #region CTOR
- public Popper() : base()
- {
- }
- #endregion
- bool _isPopped;
- string caption;
- string image;
- GraphicObject _content;
-
- public event EventHandler Pop;
- public event EventHandler Unpop;
-
- public override GraphicObject Content {
- get { return _content; }
- set {
- if (_content != null) {
- _content.LogicalParent = null;
- _content.LayoutChanged -= _content_LayoutChanged;
- _content.MouseLeave -= _content_MouseLeave;
- }
-
- _content = value;
-
- if (_content == null)
- return;
-
- _content.LogicalParent = this;
- _content.Focusable = true;
- _content.LayoutChanged += _content_LayoutChanged;
- _content.MouseLeave += _content_MouseLeave;
- }
- }
-
- void _content_MouseLeave (object sender, MouseMoveEventArgs e)
- {
- IsPopped = false;
- }
-
- void _content_LayoutChanged (object sender, LayoutChangeEventArgs e)
- {
- ILayoutable tc = Content.Parent as ILayoutable;
- if (tc == null)
- return;
- Rectangle r = this.ScreenCoordinates (this.Slot);
- if (((int)e.LayoutType & (int)LayoutingType.Width) > 0) {
- if (Content.Slot.Width < tc.ClientRectangle.Width) {
- if (r.Left + Content.Slot.Width > tc.ClientRectangle.Right)
- Content.Left = tc.ClientRectangle.Right - Content.Slot.Width;
- else
- Content.Left = r.Left;
- } else
- Content.Left = 0;
- }
- if (((int)e.LayoutType & (int)LayoutingType.Height) > 0) {
- if (Content.Slot.Height < tc.ClientRectangle.Height) {
- if (r.Bottom + Content.Slot.Height > tc.ClientRectangle.Bottom)
- Content.Top = r.Top - Content.Slot.Height;
- else
- Content.Top = r.Bottom;
- }else
- Content.Top = 0;
- }
- }
- public override void ClearBinding ()
- {
- //ensure popped window is cleared
- if (Content != null) {
- if (Content.Parent != null) {
- IGOLibHost tc = Content.Parent as IGOLibHost;
- if (tc != null)
- tc.DeleteWidget (Content);
- }
- }
- base.ClearBinding ();
- }
- public override void ResolveBindings ()
- {
- base.ResolveBindings ();
- if (Content != null)
- Content.ResolveBindings ();
- }
-
- [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to 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; }
- }
-
- [XmlAttributeAttribute()][DefaultValue("Popper")]
- public string Caption {
- get { return caption; }
- set {
- if (caption == value)
- return;
- caption = value;
- NotifyValueChanged ("Caption", caption);
- }
- }
- [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.expandable.svg")]
- public string Image {
- get { return image; }
- set {
- if (image == value)
- return;
- image = value;
- NotifyValueChanged ("Image", image);
- }
- }
-
- [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 = HostContainer;
- if (tc == null)
- return;
- if (Content != null) {
- Content.Visible = true;
- if (Content.Parent == null)
- tc.AddWidget (Content);
- tc.PutOnTop (Content);
- _content_LayoutChanged (this, new LayoutChangeEventArgs (LayoutingType.Sizing));
- }
- Pop.Raise (this, e);
- }
- public virtual void onUnpop(object sender, EventArgs e)
- {
- IGOLibHost tc = HostContainer;
- if (tc == null)
- return;
- Content.Visible = false;
- Unpop.Raise (this, e);
- }
-
- public override void onMouseClick (object sender, MouseButtonEventArgs e)
- {
- IsPopped = !IsPopped;
- base.onMouseClick (sender, e);
- }
- }
-}
+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 +{ + [DefaultTemplate("#Crow.Templates.Popper.goml")] + public class Popper : TemplatedContainer + { + #region CTOR + public Popper() : base() + { + } + #endregion + bool _isPopped; + string caption; + string image; + GraphicObject _content; + + public event EventHandler Pop; + public event EventHandler Unpop; + + public override GraphicObject Content { + get { return _content; } + set { + if (_content != null) { + _content.LogicalParent = null; + _content.LayoutChanged -= _content_LayoutChanged; + _content.MouseLeave -= _content_MouseLeave; + } + + _content = value; + + if (_content == null) + return; + + _content.LogicalParent = this; + _content.Focusable = true; + _content.LayoutChanged += _content_LayoutChanged; + _content.MouseLeave += _content_MouseLeave; + } + } + + void _content_MouseLeave (object sender, MouseMoveEventArgs e) + { + IsPopped = false; + } + + void _content_LayoutChanged (object sender, LayoutChangeEventArgs e) + { + ILayoutable tc = Content.Parent as ILayoutable; + if (tc == null) + return; + Rectangle r = this.ScreenCoordinates (this.Slot); + if (((int)e.LayoutType & (int)LayoutingType.Width) > 0) { + if (Content.Slot.Width < tc.ClientRectangle.Width) { + if (r.Left + Content.Slot.Width > tc.ClientRectangle.Right) + Content.Left = tc.ClientRectangle.Right - Content.Slot.Width; + else + Content.Left = r.Left; + } else + Content.Left = 0; + } + if (((int)e.LayoutType & (int)LayoutingType.Height) > 0) { + if (Content.Slot.Height < tc.ClientRectangle.Height) { + if (r.Bottom + Content.Slot.Height > tc.ClientRectangle.Bottom) + Content.Top = r.Top - Content.Slot.Height; + else + Content.Top = r.Bottom; + }else + Content.Top = 0; + } + } + public override void ClearBinding () + { + //ensure popped window is cleared + if (Content != null) { + if (Content.Parent != null) { + IGOLibHost tc = Content.Parent as IGOLibHost; + if (tc != null) + tc.DeleteWidget (Content); + } + } + base.ClearBinding (); + } + public override void ResolveBindings () + { + base.ResolveBindings (); + if (Content != null) + Content.ResolveBindings (); + } + + [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to 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; } + } + + [XmlAttributeAttribute()][DefaultValue("Popper")] + public string Caption { + get { return caption; } + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.expandable.svg")] + public string Image { + get { return image; } + set { + if (image == value) + return; + image = value; + NotifyValueChanged ("Image", image); + } + } + + [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 = HostContainer; + if (tc == null) + return; + if (Content != null) { + Content.Visible = true; + if (Content.Parent == null) + tc.AddWidget (Content); + tc.PutOnTop (Content); + _content_LayoutChanged (this, new LayoutChangeEventArgs (LayoutingType.Sizing)); + } + Pop.Raise (this, e); + } + public virtual void onUnpop(object sender, EventArgs e) + { + IGOLibHost tc = HostContainer; + if (tc == null) + return; + Content.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/ProgressBar.cs b/src/GraphicObjects/ProgressBar.cs index e7be280d..c8dcbb77 100644 --- a/src/GraphicObjects/ProgressBar.cs +++ b/src/GraphicObjects/ProgressBar.cs @@ -1,104 +1,104 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Cairo;
-using System.Diagnostics;
-using System.Xml.Serialization;
-using System.ComponentModel;
-
-namespace Crow
-{
- [Serializable]
- public class ProgressBar : Border
- {
- #region CTOR
- public ProgressBar() : base(){}
- public ProgressBar(int _max) : base()
- {
- Maximum = _max;
- }
- #endregion
-
- #region private fields
- int _currentValue = 0;
- int _minimum = 0;
- int _maximum = 100;
- #endregion
-
- #region public properties
- [XmlAttributeAttribute()][DefaultValue(0)]
- public int Value
- {
- get { return _currentValue; }
- set
- {
- if (_currentValue == value)
- return;
-
- _currentValue = value;
-
- if (_currentValue > Maximum)
- _currentValue = Maximum;
-
- registerForGraphicUpdate();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(0)]
- public int Minimum {
- get {return _minimum;}
- set {
- if (_minimum == value || _minimum >= Maximum)
- return;
- _minimum = value;
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(100)]
- public int Maximum {
- get {return _maximum;}
- set {
- if (_maximum == value || _maximum <= _minimum)
- return;
- _maximum = value;
- registerForGraphicUpdate();
- }
- }
- #endregion
-
- #region GraphicObject overrides
- [XmlAttributeAttribute()][DefaultValue("Gray")]
- public override Color Background {
- get { return base.Background; }
- set { base.Background = value; }
- }
- [XmlAttributeAttribute()][DefaultValue(0)]
- public override int BorderWidth {
- get { return base.BorderWidth; }
- set { base.BorderWidth = value; }
- }
- [XmlAttributeAttribute()][DefaultValue("BlueCrayola")]
- public override Color Foreground {
- get { return base.Foreground; }
- set { base.Foreground = value; }
- }
-
- protected override void onDraw (Context gr)
- {
- base.onDraw (gr);
-
- Rectangle rBack = Slot.Size;
-
- if (BorderWidth > 0)
- rBack.Inflate(-BorderWidth, -BorderWidth);
-
- rBack.Width = (int)((double)rBack.Width / Maximum * Value);
-
- gr.SetSourceColor(Foreground);
-
- CairoHelpers.CairoRectangle(gr,rBack,CornerRadius);
- gr.Fill();
- }
- #endregion
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Cairo; +using System.Diagnostics; +using System.Xml.Serialization; +using System.ComponentModel; + +namespace Crow +{ + [Serializable] + public class ProgressBar : Border + { + #region CTOR + public ProgressBar() : base(){} + public ProgressBar(int _max) : base() + { + Maximum = _max; + } + #endregion + + #region private fields + int _currentValue = 0; + int _minimum = 0; + int _maximum = 100; + #endregion + + #region public properties + [XmlAttributeAttribute()][DefaultValue(0)] + public int Value + { + get { return _currentValue; } + set + { + if (_currentValue == value) + return; + + _currentValue = value; + + if (_currentValue > Maximum) + _currentValue = Maximum; + + registerForGraphicUpdate(); + } + } + [XmlAttributeAttribute()][DefaultValue(0)] + public int Minimum { + get {return _minimum;} + set { + if (_minimum == value || _minimum >= Maximum) + return; + _minimum = value; + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue(100)] + public int Maximum { + get {return _maximum;} + set { + if (_maximum == value || _maximum <= _minimum) + return; + _maximum = value; + registerForGraphicUpdate(); + } + } + #endregion + + #region GraphicObject overrides + [XmlAttributeAttribute()][DefaultValue("Gray")] + public override Color Background { + get { return base.Background; } + set { base.Background = value; } + } + [XmlAttributeAttribute()][DefaultValue(0)] + public override int BorderWidth { + get { return base.BorderWidth; } + set { base.BorderWidth = value; } + } + [XmlAttributeAttribute()][DefaultValue("BlueCrayola")] + public override Color Foreground { + get { return base.Foreground; } + set { base.Foreground = value; } + } + + protected override void onDraw (Context gr) + { + base.onDraw (gr); + + Rectangle rBack = Slot.Size; + + if (BorderWidth > 0) + rBack.Inflate(-BorderWidth, -BorderWidth); + + rBack.Width = (int)((double)rBack.Width / Maximum * Value); + + gr.SetSourceColor(Foreground); + + CairoHelpers.CairoRectangle(gr,rBack,CornerRadius); + gr.Fill(); + } + #endregion + } +} diff --git a/src/GraphicObjects/RadioButton.cs b/src/GraphicObjects/RadioButton.cs index 5985b2c3..66e63ce4 100644 --- a/src/GraphicObjects/RadioButton.cs +++ b/src/GraphicObjects/RadioButton.cs @@ -1,93 +1,93 @@ -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;
-
-namespace Crow
-{
- [DefaultTemplate("#Crow.Templates.RadioButton.goml")]
- public class RadioButton : TemplatedControl
- {
- string caption;
- string image;
- bool isChecked;
-
- #region CTOR
- public RadioButton() : base(){}
- #endregion
-
- #region GraphicObject overrides
- [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to 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")]
- public string Caption {
- get { return caption; }
- set {
- if (caption == value)
- return;
- caption = value;
- NotifyValueChanged ("Caption", caption);
- }
- }
- [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.radiobutton.svg")]
- public string Image {
- get { return image; }
- set {
- if (image == value)
- return;
- image = value;
- NotifyValueChanged ("Image", image);
- }
- }
-
- [XmlAttributeAttribute()][DefaultValue(false)]
- public bool IsChecked
- {
- get { return isChecked; }
- set
- {
- isChecked = value;
-
- NotifyValueChanged ("IsChecked", value);
- if (isChecked)
- NotifyValueChanged ("SvgSub", "checked");
- else
- NotifyValueChanged ("SvgSub", "unchecked");
- }
- }
-
- public override void onMouseClick (object sender, MouseButtonEventArgs e)
- {
- Group pg = Parent as Group;
- if (pg != null) {
- foreach (RadioButton c in pg.Children.OfType<RadioButton>())
- c.IsChecked = (c == this);
- } else
- IsChecked = !IsChecked;
-
- base.onMouseClick (sender, e);
- }
- }
-}
+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; + +namespace Crow +{ + [DefaultTemplate("#Crow.Templates.RadioButton.goml")] + public class RadioButton : TemplatedControl + { + string caption; + string image; + bool isChecked; + + #region CTOR + public RadioButton() : base(){} + #endregion + + #region GraphicObject overrides + [XmlAttributeAttribute()][DefaultValue(true)]//overiden to get default to 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")] + public string Caption { + get { return caption; } + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + [XmlAttributeAttribute()][DefaultValue("#Crow.Images.Icons.radiobutton.svg")] + public string Image { + get { return image; } + set { + if (image == value) + return; + image = value; + NotifyValueChanged ("Image", image); + } + } + + [XmlAttributeAttribute()][DefaultValue(false)] + public bool IsChecked + { + get { return isChecked; } + set + { + isChecked = value; + + NotifyValueChanged ("IsChecked", value); + if (isChecked) + NotifyValueChanged ("SvgSub", "checked"); + else + NotifyValueChanged ("SvgSub", "unchecked"); + } + } + + public override void onMouseClick (object sender, MouseButtonEventArgs e) + { + Group pg = Parent as Group; + if (pg != null) { + foreach (RadioButton c in pg.Children.OfType<RadioButton>()) + c.IsChecked = (c == this); + } else + IsChecked = !IsChecked; + + base.onMouseClick (sender, e); + } + } +} diff --git a/src/GraphicObjects/ScrollBar.cs b/src/GraphicObjects/ScrollBar.cs index 32bc8807..9a598aba 100644 --- a/src/GraphicObjects/ScrollBar.cs +++ b/src/GraphicObjects/ScrollBar.cs @@ -1,97 +1,97 @@ -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;
-
-namespace Crow
-{
- [DefaultTemplate("#Crow.Templates.ScrollBar.goml")]
- public class ScrollBar : TemplatedControl
- {
- Orientation _orientation;
- Slider _slider;
- double _maximumScroll;
- double _scroll;
-
- public ScrollBar() : base()
- {
- }
-
- protected override void loadTemplate(GraphicObject template = null)
- {
- base.loadTemplate (template);
- _slider = this.child.FindByName ("Slider") as Slider;
- }
-
- [XmlAttributeAttribute()][DefaultValue(0.0)]
- public virtual double MaximumScroll
- {
- get { return _maximumScroll; }
- set {
- if (_maximumScroll == value)
- return;
- _maximumScroll = value;
- registerForGraphicUpdate ();
- NotifyValueChanged ("MaximumScroll", _maximumScroll);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(0.0)]
- public virtual double Scroll
- {
- get { return _scroll; }
- set {
- if (_scroll == value)
- return;
- _scroll = value;
- if (_scroll < 0.0)
- _scroll = 0.0;
- else if (_scroll > _maximumScroll)
- _scroll = _maximumScroll;
- registerForGraphicUpdate ();
- NotifyValueChanged ("Scroll", _scroll);
- }
- }
- [XmlAttributeAttribute()][DefaultValue(Orientation.Vertical)]
- public virtual Orientation Orientation
- {
- get { return _orientation; }
- set {
- if (_orientation == value)
- return;
- _orientation = value;
- NotifyValueChanged ("Orientation", _orientation);
- registerForGraphicUpdate ();
- }
- }
- public void onScrollBack (object sender, MouseButtonEventArgs e)
- {
- Scroll -= _slider.LargeIncrement;
- }
- public void onScrollForth (object sender, MouseButtonEventArgs e)
- {
- Scroll += _slider.LargeIncrement;
-
- }
-
- public void onSliderValueChange(object sender, ValueChangeEventArgs e){
- Scroll = Convert.ToDouble(e.NewValue);
- }
-
- public override void OnLayoutChanges (LayoutingType layoutType)
- {
- OpenTKGameWindow.currentWindow.CursorVisible = true;
- base.OnLayoutChanges (layoutType);
- }
- }
-}
+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; + +namespace Crow +{ + [DefaultTemplate("#Crow.Templates.ScrollBar.goml")] + public class ScrollBar : TemplatedControl + { + Orientation _orientation; + Slider _slider; + double _maximumScroll; + double _scroll; + + public ScrollBar() : base() + { + } + + protected override void loadTemplate(GraphicObject template = null) + { + base.loadTemplate (template); + _slider = this.child.FindByName ("Slider") as Slider; + } + + [XmlAttributeAttribute()][DefaultValue(0.0)] + public virtual double MaximumScroll + { + get { return _maximumScroll; } + set { + if (_maximumScroll == value) + return; + _maximumScroll = value; + registerForGraphicUpdate (); + NotifyValueChanged ("MaximumScroll", _maximumScroll); + } + } + [XmlAttributeAttribute()][DefaultValue(0.0)] + public virtual double Scroll + { + get { return _scroll; } + set { + if (_scroll == value) + return; + _scroll = value; + if (_scroll < 0.0) + _scroll = 0.0; + else if (_scroll > _maximumScroll) + _scroll = _maximumScroll; + registerForGraphicUpdate (); + NotifyValueChanged ("Scroll", _scroll); + } + } + [XmlAttributeAttribute()][DefaultValue(Orientation.Vertical)] + public virtual Orientation Orientation + { + get { return _orientation; } + set { + if (_orientation == value) + return; + _orientation = value; + NotifyValueChanged ("Orientation", _orientation); + registerForGraphicUpdate (); + } + } + public void onScrollBack (object sender, MouseButtonEventArgs e) + { + Scroll -= _slider.LargeIncrement; + } + public void onScrollForth (object sender, MouseButtonEventArgs e) + { + Scroll += _slider.LargeIncrement; + + } + + public void onSliderValueChange(object sender, ValueChangeEventArgs e){ + Scroll = Convert.ToDouble(e.NewValue); + } + + public override void OnLayoutChanges (LayoutingType layoutType) + { + OpenTKGameWindow.currentWindow.CursorVisible = true; + base.OnLayoutChanges (layoutType); + } + } +} diff --git a/src/GraphicObjects/Scroller.cs b/src/GraphicObjects/Scroller.cs index 9808fef8..be6e8993 100644 --- a/src/GraphicObjects/Scroller.cs +++ b/src/GraphicObjects/Scroller.cs @@ -1,227 +1,227 @@ -using System;
-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
-{
- public class Scroller : Container
- {
- bool _verticalScrolling;
- bool _horizontalScrolling;
- bool _scrollbarVisible;
- double _scrollX = 0.0;
- double _scrollY = 0.0;
- int scrollSpeed;
-
-
-
- #region public properties
- [XmlAttributeAttribute][DefaultValue(false)]
- public bool VerticalScrolling {
- get { return _verticalScrolling; }
- set { _verticalScrolling = value; }
- }
-
- [XmlAttributeAttribute][DefaultValue(false)]
- public bool HorizontalScrolling {
- get { return _horizontalScrolling; }
- set { _horizontalScrolling = value; }
- }
- [XmlAttributeAttribute][DefaultValue(true)]
- public bool ScrollbarVisible {
- get { return _scrollbarVisible; }
- set { _scrollbarVisible = value; }
- }
- [XmlAttributeAttribute][DefaultValue(0.0)]
- public double ScrollX {
- get {
- return _scrollX;
- }
- set {
- if (_scrollX == value)
- return;
- if (value < 0.0)
- _scrollX = 0.0;
- else if (value > Child.Slot.Width - ClientRectangle.Width)
- _scrollX = Math.Max(0.0, Child.Slot.Width - ClientRectangle.Width);
- else
- _scrollX = value;
- NotifyValueChanged("ScrollX", _scrollX);
- RegisterForRedraw();
- }
- }
- [XmlAttributeAttribute][DefaultValue(0.0)]
- public double ScrollY {
- get {
- return _scrollY;
- }
- set {
- if (_scrollY == value)
- return;
- if (value < 0.0)
- _scrollY = 0.0;
- else if (value > Child.Slot.Height - ClientRectangle.Height)
- _scrollY = Math.Max(0.0,Child.Slot.Height - ClientRectangle.Height);
- else
- _scrollY = value;
- NotifyValueChanged("ScrollY", _scrollY);
- RegisterForRedraw();
- }
- }
-
- [XmlIgnore]
- public int MaximumScroll {
- get {
- return VerticalScrolling ?
- child == null ? 0 : Child.Slot.Height - ClientRectangle.Height :
- Child.Slot.Width - ClientRectangle.Width;
- }
- }
-
- [XmlAttributeAttribute][DefaultValue(30)]
- public int ScrollSpeed {
- get { return scrollSpeed; }
- set {
- scrollSpeed = value;
- NotifyValueChanged("ScrollSpeed", scrollSpeed);
- }
- }
- #endregion
-
-
- public Scroller()
- : base(){}
-
- #region GraphicObject Overrides
- void OnChildLayoutChanges (object sender, LayoutChangeEventArgs arg)
- {
- int maxScroll = MaximumScroll;
- if (_verticalScrolling) {
- if (arg.LayoutType == LayoutingType.Height) {
- if (maxScroll < ScrollY) {
- Debug.WriteLine ("scrolly={0} maxscroll={1}", ScrollY, maxScroll);
- ScrollY = 0;
- }
- NotifyValueChanged("MaximumScroll", maxScroll);
- }
- } else if (arg.LayoutType == LayoutingType.Width) {
- if (maxScroll < ScrollX)
- ScrollX = 0;
- NotifyValueChanged("MaximumScroll", maxScroll);
- }
- }
- void onChildListCleared(object sender, EventArgs e){
- ScrollY = 0;
- ScrollX = 0;
- }
- public override T SetChild<T> (T _child)
- {
- GraphicObject c = child as GraphicObject;
- Group g = child as Group;
- if (c != null) {
- c.LayoutChanged -= OnChildLayoutChanges;
- if (g != null)
- g.ChildrenCleared -= onChildListCleared;
- }
- c = _child as GraphicObject;
- g = _child as Group;
- if (c != null) {
- c.LayoutChanged += OnChildLayoutChanges;
- if (g != null)
- g.ChildrenCleared += onChildListCleared;
- }
- return base.SetChild (_child);
- }
- #endregion
-
- #region Mouse handling
- internal Point savedMousePos;
- public override bool MouseIsIn (Point m)
- {
-// Debug.WriteLine ("Mouse in scroller: {0} scr coord:{1} mouse:{2}",
-// base.ScreenCoordinates (Slot).ContainsOrIsEqual (m),
-// base.ScreenCoordinates (Slot), m);
-
- return Visible ? base.ScreenCoordinates(Slot).ContainsOrIsEqual (m) : false;
- }
- public override void checkHoverWidget (MouseMoveEventArgs e)
- {
- savedMousePos = e.Position;
- Point m = e.Position - new Point ((int)ScrollX, (int)ScrollY);
- base.checkHoverWidget (new MouseMoveEventArgs(m.X,m.Y,e.XDelta,e.YDelta));
- }
- public override void onMouseWheel (object sender, MouseWheelEventArgs e)
- {
- //base.onMouseWheel (sender, e); base event buble to the top
-// if (MouseWheelChanged!=null)
-// MouseWheelChanged (this, e);
-
- if (Child == null)
- return;
-
- if (VerticalScrolling )
- ScrollY -= e.Delta * ScrollSpeed;
- if (HorizontalScrolling )
- ScrollX -= e.Delta * ScrollSpeed;
- }
- public override void onMouseMove (object sender, MouseMoveEventArgs e)
- {
- savedMousePos.X += e.XDelta;
- savedMousePos.Y += e.YDelta;
- base.onMouseMove (sender, new MouseMoveEventArgs(savedMousePos.X,savedMousePos.Y,e.XDelta,e.YDelta));
- }
- #endregion
-
- public override Rectangle ContextCoordinates (Rectangle r)
- {
- return base.ContextCoordinates (r) - new Point((int)ScrollX,(int)ScrollY);
- }
- public override Rectangle ScreenCoordinates (Rectangle r)
- {
- return base.ScreenCoordinates (r) - new Point((int)ScrollX,(int)ScrollY);
- }
-
- public override void registerClipRect ()
- {
- HostContainer.redrawClip.AddRectangle (base.ScreenCoordinates(Slot));
- }
-
- 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);
- //clip.Srcoll (this);
-
- base.Paint (ref ctx, clip);
-
- //clip to client zone
- ctx.Rectangle(Parent.ContextCoordinates(ClientRectangle + Slot.Position));
- ctx.Clip();
-
-// if (clip != null)
-// clip.Srcoll (this);
- // if (clip != null)
- // clip.Rebase(this);
-
- if (Child != null)
- Child.Paint(ref ctx, clip);
-
- ctx.Restore();
- }
- }
-}
+using System; +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 +{ + public class Scroller : Container + { + bool _verticalScrolling; + bool _horizontalScrolling; + bool _scrollbarVisible; + double _scrollX = 0.0; + double _scrollY = 0.0; + int scrollSpeed; + + + + #region public properties + [XmlAttributeAttribute][DefaultValue(false)] + public bool VerticalScrolling { + get { return _verticalScrolling; } + set { _verticalScrolling = value; } + } + + [XmlAttributeAttribute][DefaultValue(false)] + public bool HorizontalScrolling { + get { return _horizontalScrolling; } + set { _horizontalScrolling = value; } + } + [XmlAttributeAttribute][DefaultValue(true)] + public bool ScrollbarVisible { + get { return _scrollbarVisible; } + set { _scrollbarVisible = value; } + } + [XmlAttributeAttribute][DefaultValue(0.0)] + public double ScrollX { + get { + return _scrollX; + } + set { + if (_scrollX == value) + return; + if (value < 0.0) + _scrollX = 0.0; + else if (value > Child.Slot.Width - ClientRectangle.Width) + _scrollX = Math.Max(0.0, Child.Slot.Width - ClientRectangle.Width); + else + _scrollX = value; + NotifyValueChanged("ScrollX", _scrollX); + RegisterForRedraw(); + } + } + [XmlAttributeAttribute][DefaultValue(0.0)] + public double ScrollY { + get { + return _scrollY; + } + set { + if (_scrollY == value) + return; + if (value < 0.0) + _scrollY = 0.0; + else if (value > Child.Slot.Height - ClientRectangle.Height) + _scrollY = Math.Max(0.0,Child.Slot.Height - ClientRectangle.Height); + else + _scrollY = value; + NotifyValueChanged("ScrollY", _scrollY); + RegisterForRedraw(); + } + } + + [XmlIgnore] + public int MaximumScroll { + get { + return VerticalScrolling ? + child == null ? 0 : Child.Slot.Height - ClientRectangle.Height : + Child.Slot.Width - ClientRectangle.Width; + } + } + + [XmlAttributeAttribute][DefaultValue(30)] + public int ScrollSpeed { + get { return scrollSpeed; } + set { + scrollSpeed = value; + NotifyValueChanged("ScrollSpeed", scrollSpeed); + } + } + #endregion + + + public Scroller() + : base(){} + + #region GraphicObject Overrides + void OnChildLayoutChanges (object sender, LayoutChangeEventArgs arg) + { + int maxScroll = MaximumScroll; + if (_verticalScrolling) { + if (arg.LayoutType == LayoutingType.Height) { + if (maxScroll < ScrollY) { + Debug.WriteLine ("scrolly={0} maxscroll={1}", ScrollY, maxScroll); + ScrollY = 0; + } + NotifyValueChanged("MaximumScroll", maxScroll); + } + } else if (arg.LayoutType == LayoutingType.Width) { + if (maxScroll < ScrollX) + ScrollX = 0; + NotifyValueChanged("MaximumScroll", maxScroll); + } + } + void onChildListCleared(object sender, EventArgs e){ + ScrollY = 0; + ScrollX = 0; + } + public override T SetChild<T> (T _child) + { + GraphicObject c = child as GraphicObject; + Group g = child as Group; + if (c != null) { + c.LayoutChanged -= OnChildLayoutChanges; + if (g != null) + g.ChildrenCleared -= onChildListCleared; + } + c = _child as GraphicObject; + g = _child as Group; + if (c != null) { + c.LayoutChanged += OnChildLayoutChanges; + if (g != null) + g.ChildrenCleared += onChildListCleared; + } + return base.SetChild (_child); + } + #endregion + + #region Mouse handling + internal Point savedMousePos; + public override bool MouseIsIn (Point m) + { +// Debug.WriteLine ("Mouse in scroller: {0} scr coord:{1} mouse:{2}", +// base.ScreenCoordinates (Slot).ContainsOrIsEqual (m), +// base.ScreenCoordinates (Slot), m); + + return Visible ? base.ScreenCoordinates(Slot).ContainsOrIsEqual (m) : false; + } + public override void checkHoverWidget (MouseMoveEventArgs e) + { + savedMousePos = e.Position; + Point m = e.Position - new Point ((int)ScrollX, (int)ScrollY); + base.checkHoverWidget (new MouseMoveEventArgs(m.X,m.Y,e.XDelta,e.YDelta)); + } + public override void onMouseWheel (object sender, MouseWheelEventArgs e) + { + //base.onMouseWheel (sender, e); base event buble to the top +// if (MouseWheelChanged!=null) +// MouseWheelChanged (this, e); + + if (Child == null) + return; + + if (VerticalScrolling ) + ScrollY -= e.Delta * ScrollSpeed; + if (HorizontalScrolling ) + ScrollX -= e.Delta * ScrollSpeed; + } + public override void onMouseMove (object sender, MouseMoveEventArgs e) + { + savedMousePos.X += e.XDelta; + savedMousePos.Y += e.YDelta; + base.onMouseMove (sender, new MouseMoveEventArgs(savedMousePos.X,savedMousePos.Y,e.XDelta,e.YDelta)); + } + #endregion + + public override Rectangle ContextCoordinates (Rectangle r) + { + return base.ContextCoordinates (r) - new Point((int)ScrollX,(int)ScrollY); + } + public override Rectangle ScreenCoordinates (Rectangle r) + { + return base.ScreenCoordinates (r) - new Point((int)ScrollX,(int)ScrollY); + } + + public override void registerClipRect () + { + HostContainer.redrawClip.AddRectangle (base.ScreenCoordinates(Slot)); + } + + 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); + //clip.Srcoll (this); + + base.Paint (ref ctx, clip); + + //clip to client zone + ctx.Rectangle(Parent.ContextCoordinates(ClientRectangle + Slot.Position)); + ctx.Clip(); + +// if (clip != null) +// clip.Srcoll (this); + // if (clip != null) + // clip.Rebase(this); + + if (Child != null) + Child.Paint(ref ctx, clip); + + ctx.Restore(); + } + } +} diff --git a/src/GraphicObjects/Slider.cs b/src/GraphicObjects/Slider.cs index 27c162a0..a931934a 100644 --- a/src/GraphicObjects/Slider.cs +++ b/src/GraphicObjects/Slider.cs @@ -1,199 +1,199 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Cairo;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using System.Diagnostics;
-
-namespace Crow
-{
- public class Slider : NumericControl
- {
- #region CTOR
- public Slider() : base()
- {}
- public Slider(double minimum, double maximum, double step)
- : base(minimum,maximum,step)
- {
- }
- #endregion
-
- #region implemented abstract members of TemplatedControl
-
- protected override void loadTemplate (GraphicObject template = null)
- {
-
- }
-
- #endregion
-
- #region private fields
- Rectangle cursor;
- int _cursorSize;
- Color _cursorColor;
- Orientation _orientation;
- bool holdCursor = false;
- #endregion
-
- protected double unity;
-
- #region Public properties
- [XmlAttributeAttribute()][DefaultValue("BlueGray")]
- public virtual Color CursorColor {
- get { return _cursorColor; }
- set {
- _cursorColor = value;
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(20)]
- public virtual int CursorSize {
- get { return _cursorSize; }
- set {
- _cursorSize = value;
- registerForGraphicUpdate ();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(Orientation.Horizontal)]
- public virtual Orientation Orientation
- {
- get { return _orientation; }
- set { _orientation = value; }
- }
- #endregion
- [XmlAttributeAttribute()][DefaultValue(10.0)]
- public override double Maximum {
- get { return base.Maximum; }
- set {
- if (value == base.Maximum)
- return;
- base.Maximum = value;
- LargeIncrement = base.Maximum / 10.0;
- SmallIncrement = LargeIncrement / 5.0;
-
- }
- }
- #region GraphicObject Overrides
- [XmlAttributeAttribute()][DefaultValue("Gray")]
- public override Color Background {
- get { return base.Background; }
- set { base.Background = value; }
- }
- [XmlAttributeAttribute()][DefaultValue(true)]
- public override bool Focusable
- {
- get { return base.Focusable; }
- set { base.Focusable = value; }
- }
- //TODO:seems strange to trigger layout computation in an
- //overriding of updateGraphic
- protected override void UpdateGraphic ()
- {
- if (Maximum > 0)
- computeCursorPosition();
- base.UpdateGraphic ();
- }
-
- protected override void onDraw (Context gr)
- {
- base.onDraw (gr);
- if (Maximum <= 0)
- return;
- Rectangle r = ClientRectangle;
- PointD pStart;
- PointD pEnd;
- if (_orientation == Orientation.Horizontal) {
- pStart = r.TopLeft + new Point (_cursorSize / 2, r.Height / 2);
- pEnd = r.TopRight + new Point (-_cursorSize / 2, r.Height / 2);
- } else {
- pStart = r.TopLeft + new Point (r.Width / 2, _cursorSize / 2);
- pEnd = r.BottomLeft + new Point (r.Width / 2,- _cursorSize / 2);
- }
-
- DrawGraduations (gr, pStart,pEnd);
-
- DrawCursor (gr, cursor);
- }
- #endregion
-
- protected virtual void DrawGraduations(Context gr, PointD pStart, PointD pEnd)
- {
- gr.SetSourceColor(Foreground);
-
- gr.LineWidth = 1;
- gr.MoveTo(pStart);
- gr.LineTo(pEnd);
-
- gr.Stroke();
-
- }
- protected virtual void DrawCursor(Context gr, Rectangle _cursor)
- {
- gr.SetSourceColor(CursorColor);
- CairoHelpers.CairoRectangle (gr, _cursor, CornerRadius);
- gr.FillPreserve();
- }
-
- void computeCursorPosition()
- {
- Rectangle r = ClientRectangle;
- PointD p1;
-
- if (_orientation == Orientation.Horizontal) {
- cursor = new Rectangle (new Size (_cursorSize, (int)(r.Height)));
- p1 = r.TopLeft + new Point (_cursorSize / 2, r.Height / 2);
- unity = (double)(r.Width - _cursorSize) / (Maximum - Minimum);
- cursor.TopLeft = new Point (r.Left + (int)(Value * unity),
- (int)(p1.Y - cursor.Height / 2));
- } else {
- cursor = new Rectangle (new Size ((int)(r.Width), _cursorSize));
- p1 = r.TopLeft + new Point (r.Width / 2, _cursorSize / 2);
- unity = (double)(r.Height - _cursorSize) / (Maximum - Minimum);
- cursor.TopLeft = new Point ((int)(p1.X - r.Width / 2),
- r.Top + (int)(Value * unity));
- }
- cursor.Inflate (-1);
- }
-
- #region mouse handling
- public override void onMouseDown (object sender, OpenTK.Input.MouseButtonEventArgs e)
- {
- base.onMouseDown (sender, e);
-
- Rectangle cursInScreenCoord = ScreenCoordinates (cursor + Slot.Position);
- if (cursInScreenCoord.ContainsOrIsEqual (e.Position))
- holdCursor = true;
- else if (_orientation == Orientation.Horizontal) {
- if (e.Position.X < cursInScreenCoord.Left)
- Value -= LargeIncrement;
- else
- Value += LargeIncrement;
- } else {
- if (e.Position.Y < cursInScreenCoord.Top)
- Value -= LargeIncrement;
- else
- Value += LargeIncrement;
- }
- }
- public override void onMouseUp (object sender, OpenTK.Input.MouseButtonEventArgs e)
- {
- base.onMouseUp (sender, e);
-
- holdCursor = false;
- }
- public override void onMouseMove (object sender, OpenTK.Input.MouseMoveEventArgs e)
- {
- if (holdCursor) {
- if (_orientation == Orientation.Horizontal)
- Value += (double)e.XDelta / unity;
- else
- Value += (double)e.YDelta / unity;
- }
-
- base.onMouseMove (sender, e);
- }
- #endregion
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Cairo; +using System.Xml.Serialization; +using System.ComponentModel; +using System.Diagnostics; + +namespace Crow +{ + public class Slider : NumericControl + { + #region CTOR + public Slider() : base() + {} + public Slider(double minimum, double maximum, double step) + : base(minimum,maximum,step) + { + } + #endregion + + #region implemented abstract members of TemplatedControl + + protected override void loadTemplate (GraphicObject template = null) + { + + } + + #endregion + + #region private fields + Rectangle cursor; + int _cursorSize; + Color _cursorColor; + Orientation _orientation; + bool holdCursor = false; + #endregion + + protected double unity; + + #region Public properties + [XmlAttributeAttribute()][DefaultValue("BlueGray")] + public virtual Color CursorColor { + get { return _cursorColor; } + set { + _cursorColor = value; + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue(20)] + public virtual int CursorSize { + get { return _cursorSize; } + set { + _cursorSize = value; + registerForGraphicUpdate (); + } + } + [XmlAttributeAttribute()][DefaultValue(Orientation.Horizontal)] + public virtual Orientation Orientation + { + get { return _orientation; } + set { _orientation = value; } + } + #endregion + [XmlAttributeAttribute()][DefaultValue(10.0)] + public override double Maximum { + get { return base.Maximum; } + set { + if (value == base.Maximum) + return; + base.Maximum = value; + LargeIncrement = base.Maximum / 10.0; + SmallIncrement = LargeIncrement / 5.0; + + } + } + #region GraphicObject Overrides + [XmlAttributeAttribute()][DefaultValue("Gray")] + public override Color Background { + get { return base.Background; } + set { base.Background = value; } + } + [XmlAttributeAttribute()][DefaultValue(true)] + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + //TODO:seems strange to trigger layout computation in an + //overriding of updateGraphic + protected override void UpdateGraphic () + { + if (Maximum > 0) + computeCursorPosition(); + base.UpdateGraphic (); + } + + protected override void onDraw (Context gr) + { + base.onDraw (gr); + if (Maximum <= 0) + return; + Rectangle r = ClientRectangle; + PointD pStart; + PointD pEnd; + if (_orientation == Orientation.Horizontal) { + pStart = r.TopLeft + new Point (_cursorSize / 2, r.Height / 2); + pEnd = r.TopRight + new Point (-_cursorSize / 2, r.Height / 2); + } else { + pStart = r.TopLeft + new Point (r.Width / 2, _cursorSize / 2); + pEnd = r.BottomLeft + new Point (r.Width / 2,- _cursorSize / 2); + } + + DrawGraduations (gr, pStart,pEnd); + + DrawCursor (gr, cursor); + } + #endregion + + protected virtual void DrawGraduations(Context gr, PointD pStart, PointD pEnd) + { + gr.SetSourceColor(Foreground); + + gr.LineWidth = 1; + gr.MoveTo(pStart); + gr.LineTo(pEnd); + + gr.Stroke(); + + } + protected virtual void DrawCursor(Context gr, Rectangle _cursor) + { + gr.SetSourceColor(CursorColor); + CairoHelpers.CairoRectangle (gr, _cursor, CornerRadius); + gr.FillPreserve(); + } + + void computeCursorPosition() + { + Rectangle r = ClientRectangle; + PointD p1; + + if (_orientation == Orientation.Horizontal) { + cursor = new Rectangle (new Size (_cursorSize, (int)(r.Height))); + p1 = r.TopLeft + new Point (_cursorSize / 2, r.Height / 2); + unity = (double)(r.Width - _cursorSize) / (Maximum - Minimum); + cursor.TopLeft = new Point (r.Left + (int)(Value * unity), + (int)(p1.Y - cursor.Height / 2)); + } else { + cursor = new Rectangle (new Size ((int)(r.Width), _cursorSize)); + p1 = r.TopLeft + new Point (r.Width / 2, _cursorSize / 2); + unity = (double)(r.Height - _cursorSize) / (Maximum - Minimum); + cursor.TopLeft = new Point ((int)(p1.X - r.Width / 2), + r.Top + (int)(Value * unity)); + } + cursor.Inflate (-1); + } + + #region mouse handling + public override void onMouseDown (object sender, OpenTK.Input.MouseButtonEventArgs e) + { + base.onMouseDown (sender, e); + + Rectangle cursInScreenCoord = ScreenCoordinates (cursor + Slot.Position); + if (cursInScreenCoord.ContainsOrIsEqual (e.Position)) + holdCursor = true; + else if (_orientation == Orientation.Horizontal) { + if (e.Position.X < cursInScreenCoord.Left) + Value -= LargeIncrement; + else + Value += LargeIncrement; + } else { + if (e.Position.Y < cursInScreenCoord.Top) + Value -= LargeIncrement; + else + Value += LargeIncrement; + } + } + public override void onMouseUp (object sender, OpenTK.Input.MouseButtonEventArgs e) + { + base.onMouseUp (sender, e); + + holdCursor = false; + } + public override void onMouseMove (object sender, OpenTK.Input.MouseMoveEventArgs e) + { + if (holdCursor) { + if (_orientation == Orientation.Horizontal) + Value += (double)e.XDelta / unity; + else + Value += (double)e.YDelta / unity; + } + + base.onMouseMove (sender, e); + } + #endregion + } +} diff --git a/src/GraphicObjects/TextBox.cs b/src/GraphicObjects/TextBox.cs index 7d67e825..6af75f1e 100644 --- a/src/GraphicObjects/TextBox.cs +++ b/src/GraphicObjects/TextBox.cs @@ -1,202 +1,202 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using OpenTK.Input;
-using Cairo;
-using System.Diagnostics;
-using System.Xml.Serialization;
-using System.Globalization;
-using System.ComponentModel;
-using System.Runtime.InteropServices;
-
-namespace Crow
-{
- public class TextBox : Label
- {
- #region CTOR
- public TextBox(string _initialValue)
- : base(_initialValue)
- {
-
- }
-
- public TextBox()
- { }
- #endregion
-
- #region GraphicObject overrides
- [XmlIgnore]public override bool HasFocus //trigger update when lost focus to errase text beam
- {
- get
- {
- return base.HasFocus;
- }
- set
- {
- base.HasFocus = value;
- registerForGraphicUpdate();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(true)]
- public override bool Focusable
- {
- get { return base.Focusable; }
- set { base.Focusable = value; }
- }
- [XmlAttributeAttribute()][DefaultValue("White")]
- public override Color Background {
- get { return base.Background; }
- set { base.Background = value; }
- }
- [XmlAttributeAttribute()][DefaultValue("Black")]
- public override Color Foreground {
- get { return base.Foreground; }
- set { base.Foreground = value; }
- }
-
- protected override void onDraw (Context gr)
- {
- base.onDraw (gr);
- FontExtents fe = gr.FontExtents;
- }
- #endregion
-
- public event EventHandler<TextChangeEventArgs> TextChanged;
-
- public virtual void OnTextChanged(Object sender, TextChangeEventArgs e)
- {
- TextChanged.Raise (this, e);
- }
-
- #region Keyboard handling
- public override void onKeyDown (object sender, KeyboardKeyEventArgs e)
- {
- base.onKeyDown (sender, e);
-
- Key key = e.Key;
-
- switch (key)
- {
- case Key.Back:
- if (!selectionIsEmpty)
- {
-// Text = Text.Remove(selectionStart, selectionEnd - selectionStart);
-// selReleasePos = -1;
-// currentCol = selBeginPos;
- }
- else
- this.DeleteChar();
- break;
- case Key.Clear:
- break;
- case Key.Delete:
- if (selectionIsEmpty)
- CurrentColumn++;
- this.DeleteChar ();
- break;
- case Key.Enter:
- case Key.KeypadEnter:
- OnTextChanged(this,new TextChangeEventArgs(Text));
- break;
- case Key.Escape:
- Text = "";
- CurrentColumn = 0;
- SelRelease = -1;
- break;
- case Key.Home:
- //TODO
- if (e.Control)
- CurrentLine = 0;
- CurrentColumn = 0;
- break;
- case Key.End:
- if (e.Control)
- CurrentLine = int.MaxValue;
- CurrentColumn = int.MaxValue;
- break;
- case Key.Insert:
- break;
- case Key.Left:
- CurrentColumn--;
- break;
- case Key.Right:
- CurrentColumn++;
- break;
- case Key.Up:
- CurrentLine--;
- break;
- case Key.Down:
- CurrentLine++;
- break;
- case Key.Menu:
- break;
- case Key.NumLock:
- break;
- case Key.PageDown:
- break;
- case Key.PageUp:
- break;
- case Key.RWin:
- break;
- case Key.Tab:
- this.Insert("\t");
- break;
- case Key.KeypadDecimal:
- this.Insert (".");
- break;
- case Key.Space:
- this.Insert(" ");
- break;
- case Key.KeypadDivide:
- case Key.Slash:
- this.Insert("/");
- break;
- case Key.KeypadMultiply:
- this.Insert("*");
- break;
- case Key.KeypadMinus:
- case Key.Minus:
- this.Insert("-");
- break;
- case Key.KeypadPlus:
- case Key.Plus:
- this.Insert("+");
- break;
- case Key.ShiftLeft:
- case Key.ShiftRight:
- case Key.AltLeft:
- case Key.AltRight:
- break;
- case Key.Semicolon:
- this.Insert(";");
- break;
- default:
- if (!selectionIsEmpty)
- {
-// Text = Text.Remove(selectionStart, selectionEnd - selectionStart);
-// currentCol = selBeginPos;
- }
-
- string k = "?";
- if ((char)key >= 67 && (char)key <= 76)
- k = ((int)key - 67).ToString();
- else if ((char)key >= 109 && (char)key <= 118)
- k = ((int)key - 109).ToString();
- else if (e.Shift)
- k = key.ToString();
- else
- k = key.ToString().ToLower();
-
- this.Insert (k);
-
- SelRelease = -1;
- SelBegin = new Point(CurrentColumn, SelBegin.Y);
-
- break;
- }
- registerForGraphicUpdate();
- }
- #endregion
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenTK.Input; +using Cairo; +using System.Diagnostics; +using System.Xml.Serialization; +using System.Globalization; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace Crow +{ + public class TextBox : Label + { + #region CTOR + public TextBox(string _initialValue) + : base(_initialValue) + { + + } + + public TextBox() + { } + #endregion + + #region GraphicObject overrides + [XmlIgnore]public override bool HasFocus //trigger update when lost focus to errase text beam + { + get + { + return base.HasFocus; + } + set + { + base.HasFocus = value; + registerForGraphicUpdate(); + } + } + [XmlAttributeAttribute()][DefaultValue(true)] + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } + [XmlAttributeAttribute()][DefaultValue("White")] + public override Color Background { + get { return base.Background; } + set { base.Background = value; } + } + [XmlAttributeAttribute()][DefaultValue("Black")] + public override Color Foreground { + get { return base.Foreground; } + set { base.Foreground = value; } + } + + protected override void onDraw (Context gr) + { + base.onDraw (gr); + FontExtents fe = gr.FontExtents; + } + #endregion + + public event EventHandler<TextChangeEventArgs> TextChanged; + + public virtual void OnTextChanged(Object sender, TextChangeEventArgs e) + { + TextChanged.Raise (this, e); + } + + #region Keyboard handling + public override void onKeyDown (object sender, KeyboardKeyEventArgs e) + { + base.onKeyDown (sender, e); + + Key key = e.Key; + + switch (key) + { + case Key.Back: + if (!selectionIsEmpty) + { +// Text = Text.Remove(selectionStart, selectionEnd - selectionStart); +// selReleasePos = -1; +// currentCol = selBeginPos; + } + else + this.DeleteChar(); + break; + case Key.Clear: + break; + case Key.Delete: + if (selectionIsEmpty) + CurrentColumn++; + this.DeleteChar (); + break; + case Key.Enter: + case Key.KeypadEnter: + OnTextChanged(this,new TextChangeEventArgs(Text)); + break; + case Key.Escape: + Text = ""; + CurrentColumn = 0; + SelRelease = -1; + break; + case Key.Home: + //TODO + if (e.Control) + CurrentLine = 0; + CurrentColumn = 0; + break; + case Key.End: + if (e.Control) + CurrentLine = int.MaxValue; + CurrentColumn = int.MaxValue; + break; + case Key.Insert: + break; + case Key.Left: + CurrentColumn--; + break; + case Key.Right: + CurrentColumn++; + break; + case Key.Up: + CurrentLine--; + break; + case Key.Down: + CurrentLine++; + break; + case Key.Menu: + break; + case Key.NumLock: + break; + case Key.PageDown: + break; + case Key.PageUp: + break; + case Key.RWin: + break; + case Key.Tab: + this.Insert("\t"); + break; + case Key.KeypadDecimal: + this.Insert ("."); + break; + case Key.Space: + this.Insert(" "); + break; + case Key.KeypadDivide: + case Key.Slash: + this.Insert("/"); + break; + case Key.KeypadMultiply: + this.Insert("*"); + break; + case Key.KeypadMinus: + case Key.Minus: + this.Insert("-"); + break; + case Key.KeypadPlus: + case Key.Plus: + this.Insert("+"); + break; + case Key.ShiftLeft: + case Key.ShiftRight: + case Key.AltLeft: + case Key.AltRight: + break; + case Key.Semicolon: + this.Insert(";"); + break; + default: + if (!selectionIsEmpty) + { +// Text = Text.Remove(selectionStart, selectionEnd - selectionStart); +// currentCol = selBeginPos; + } + + string k = "?"; + if ((char)key >= 67 && (char)key <= 76) + k = ((int)key - 67).ToString(); + else if ((char)key >= 109 && (char)key <= 118) + k = ((int)key - 109).ToString(); + else if (e.Shift) + k = key.ToString(); + else + k = key.ToString().ToLower(); + + this.Insert (k); + + SelRelease = -1; + SelBegin = new Point(CurrentColumn, SelBegin.Y); + + break; + } + registerForGraphicUpdate(); + } + #endregion + } +} diff --git a/src/GraphicObjects/TextRun.cs b/src/GraphicObjects/TextRun.cs index 6201f7c1..1c539c67 100644 --- a/src/GraphicObjects/TextRun.cs +++ b/src/GraphicObjects/TextRun.cs @@ -1,333 +1,333 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Cairo;
-using System.Text.RegularExpressions;
-using System.Xml.Serialization;
-using System.ComponentModel;
-using OpenTK.Input;
-
-namespace Crow
-{
- [Serializable]
- public class TextRun : GraphicObject
- {
- #region CTOR
- public TextRun()
- {
-
- }
- public TextRun(string _text)
- : base()
- {
- Text = _text;
- }
- #endregion
-
- //TODO:change protected to private
-
- #region private and protected fields
- protected string _text = "label";
- Alignment _textAlignment = Alignment.LeftCenter;
- bool _multiline;
- bool wordWrap;
- protected Rectangle rText;
- protected float widthRatio = 1f;
- protected float heightRatio = 1f;
- protected FontExtents fe;
- protected TextExtents te;
- #endregion
-
-
- [XmlAttributeAttribute()][DefaultValue(Alignment.LeftCenter)]
- public Alignment TextAlignment
- {
- get { return _textAlignment; }
- set { _textAlignment = value; }
- }
- [XmlAttributeAttribute()][DefaultValue("label")]
- public string Text
- {
- get {
- return lines == null ?
- _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j);
- }
- set
- {
- if (_text == value)
- return;
-
- registerForGraphicUpdate();
- this.RegisterForLayouting ((int)LayoutingType.Sizing);
-
-
- _text = value;
-
- if (string.IsNullOrEmpty(_text))
- _text = "";
-
- lines = getLines;
- }
- }
- [XmlAttributeAttribute()][DefaultValue(false)]
- public bool Multiline
- {
- get { return _multiline; }
- set
- {
- _multiline = value;
- registerForGraphicUpdate();
- }
- }
- [XmlAttributeAttribute()][DefaultValue(false)]
- public bool WordWrap {
- get {
- return wordWrap;
- }
- set {
- if (wordWrap == value)
- return;
- wordWrap = value;
- registerForGraphicUpdate();
- }
- }
-
- List<string> lines;
- List<string> getLines {
- get {
- return _multiline ?
- Regex.Split (_text, "\r\n|\r|\n").ToList() :
- new List<string>(new string[] { _text });
- }
- }
-
- #region GraphicObject overrides
- [XmlAttributeAttribute()][DefaultValue(-1)]
- public override int Width {
- get { return base.Width; }
- set { base.Width = value; }
- }
- [XmlAttributeAttribute()][DefaultValue(-1)]
- public override int Height {
- get { return base.Height; }
- set { base.Height = value; }
- }
- [XmlAttributeAttribute()][DefaultValue(2)]
- public override int Margin {
- get { return base.Margin; }
- set { base.Margin = value; }
- }
-
- protected override Size measureRawSize()
- {
- Size size;
-
- 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 ();
-
- gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
- gr.SetFontSize (Font.Size);
-
- te = new TextExtents();
-
- foreach (string s in lines) {
- string l = s.Replace("\t", new String (' ', Interface.TabSize));
-
-#if _WIN32 || _WIN64
- TextExtents tmp = gr.TextExtents(str.ToUtf8());
-#elif __linux__
- TextExtents tmp = gr.TextExtents (l);
-#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 size;;
- }
- protected override void onDraw (Context gr)
- {
- base.onDraw (gr);
-
- gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
- gr.SetFontSize (Font.Size);
-
- gr.Antialias = Antialias.Subpixel;
- //gr.FontOptions.Antialias = Antialias.Subpixel;
- //gr.FontOptions.HintMetrics = HintMetrics.On;
-
- rText = new Rectangle(measureRawSize());
- rText.Width -= 2 * Margin;
- rText.Height -= 2 * Margin;
-
- widthRatio = 1f;
- heightRatio = 1f;
-
- Rectangle cb = ClientRectangle;
-
- //ignore text alignment if size to content = true
- //or if text size is larger than client bounds
- if (Bounds.Size < 0 || rText.Width > cb.Width)
- {
- rText.X = cb.X;
- rText.Y = cb.Y;
- }else {
-
- switch (TextAlignment)
- {
- case Alignment.None:
- break;
- case Alignment.TopLeft: //ok
- rText.X = cb.X;
- rText.Y = cb.Y;
- break;
- case Alignment.TopCenter: //ok
- rText.Y = cb.Y;
- rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
- break;
- case Alignment.TopRight: //ok
- rText.X = cb.Right - rText.Width;
- rText.Y = cb.Y;
- break;
- case Alignment.TopStretch://ok
- heightRatio = widthRatio = (float)cb.Width / rText.Width;
- rText.X = cb.X;
- rText.Y = cb.Y;
- rText.Width = cb.Width;
- rText.Height = (int)(rText.Height * heightRatio);
- break;
- case Alignment.LeftCenter://ok
- rText.X = cb.X;
- rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
- break;
- case Alignment.LeftStretch://ok
- heightRatio = widthRatio = (float)cb.Height / rText.Height;
- rText.X = cb.X;
- rText.Y = cb.Y;
- rText.Height = cb.Height;
- rText.Width = (int)(widthRatio * cb.Width);
- break;
- case Alignment.RightCenter://ok
- rText.X = cb.X + cb.Width - rText.Width;
- rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
- break;
- case Alignment.RightStretch://ok
- heightRatio = widthRatio = (float)cb.Height / rText.Height;
- rText.Height = cb.Height;
- rText.Width = (int)(widthRatio * cb.Width);
- rText.X = cb.X;
- rText.Y = cb.Y;
- break;
- case Alignment.BottomCenter://ok
- rText.X = cb.Width / 2 - rText.Width / 2;
- rText.Y = cb.Height - rText.Height;
- break;
- case Alignment.BottomStretch://ok
- heightRatio = widthRatio = (float)cb.Width / rText.Width;
- rText.Width = cb.Width;
- rText.Height = (int)(rText.Height * heightRatio);
- rText.Y = cb.Bottom - rText.Height;
- rText.X = cb.X;
- break;
- case Alignment.BottomLeft://ok
- rText.X = cb.X;
- rText.Y = cb.Bottom - rText.Height;
- break;
- case Alignment.BottomRight://ok
- rText.Y = cb.Bottom - rText.Height;
- rText.X = cb.Right - rText.Width;
- break;
- case Alignment.Center://ok
- rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
- rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
- break;
- case Alignment.Fit://ok, peut être mieu aligné
- widthRatio = (float)cb.Width / rText.Width;
- heightRatio = (float)cb.Height / rText.Height;
- rText = cb;
- break;
- case Alignment.HorizontalStretch://ok
- heightRatio = widthRatio = (float)cb.Width / rText.Width;
- rText.Width = cb.Width;
- rText.Height = (int)(heightRatio * rText.Height);
- rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2;
- rText.X = cb.X;
- break;
- case Alignment.VerticalStretch://ok
- heightRatio = widthRatio = (float)cb.Height / rText.Height;
- rText.Height = cb.Height;
- rText.Width = (int)(widthRatio * rText.Width);
- rText.X = cb.X + cb.Width / 2 - rText.Width / 2;
- rText.Y = cb.Y;
- break;
- default:
- break;
- }
- }
-
- gr.FontMatrix = new Matrix(widthRatio * Font.Size, 0, 0, heightRatio * Font.Size, 0, 0);
-
-
- int curLineCount = 0;
- for (int i = 0;i < lines.Count;i++) {
- string l = lines [i].Replace ("\t", new String (' ', Interface.TabSize));
- List<string> wl = new List<string> ();
- int lineLength = (int)gr.TextExtents (l).XAdvance;
-
- if (wordWrap && lineLength > cb.Width) {
- string tmpLine = "";
- int curChar = 0;
- while (curChar < l.Length) {
- tmpLine += l [curChar];
- if ((int)gr.TextExtents (tmpLine).XAdvance > cb.Width) {
- tmpLine = tmpLine.Remove (tmpLine.Length - 1);
- wl.Add (tmpLine);
- tmpLine = "";
- continue;
- }
- curChar++;
- }
- wl.Add (tmpLine);
- } else
- wl.Add (l);
-
- foreach (string ll in wl) {
- lineLength = (int)gr.TextExtents (ll).XAdvance;
-
-
- if (string.IsNullOrWhiteSpace (ll)) {
- curLineCount++;
- continue;
- }
-
- gr.SetSourceColor (Foreground);
- gr.MoveTo (rText.X, rText.Y + fe.Ascent + fe.Height * curLineCount);
-
- #if _WIN32 || _WIN64
- gr.ShowText(ll.ToUtf8());
- #elif __linux__
- gr.ShowText (ll);
- #endif
- gr.Fill ();
-
- curLineCount++;
-
- }
- }
- }
- #endregion
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using Cairo; +using System.Text.RegularExpressions; +using System.Xml.Serialization; +using System.ComponentModel; +using OpenTK.Input; + +namespace Crow +{ + [Serializable] + public class TextRun : GraphicObject + { + #region CTOR + public TextRun() + { + + } + public TextRun(string _text) + : base() + { + Text = _text; + } + #endregion + + //TODO:change protected to private + + #region private and protected fields + protected string _text = "label"; + Alignment _textAlignment = Alignment.LeftCenter; + bool _multiline; + bool wordWrap; + protected Rectangle rText; + protected float widthRatio = 1f; + protected float heightRatio = 1f; + protected FontExtents fe; + protected TextExtents te; + #endregion + + + [XmlAttributeAttribute()][DefaultValue(Alignment.LeftCenter)] + public Alignment TextAlignment + { + get { return _textAlignment; } + set { _textAlignment = value; } + } + [XmlAttributeAttribute()][DefaultValue("label")] + public string Text + { + get { + return lines == null ? + _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j); + } + set + { + if (_text == value) + return; + + registerForGraphicUpdate(); + this.RegisterForLayouting ((int)LayoutingType.Sizing); + + + _text = value; + + if (string.IsNullOrEmpty(_text)) + _text = ""; + + lines = getLines; + } + } + [XmlAttributeAttribute()][DefaultValue(false)] + public bool Multiline + { + get { return _multiline; } + set + { + _multiline = value; + registerForGraphicUpdate(); + } + } + [XmlAttributeAttribute()][DefaultValue(false)] + public bool WordWrap { + get { + return wordWrap; + } + set { + if (wordWrap == value) + return; + wordWrap = value; + registerForGraphicUpdate(); + } + } + + List<string> lines; + List<string> getLines { + get { + return _multiline ? + Regex.Split (_text, "\r\n|\r|\n").ToList() : + new List<string>(new string[] { _text }); + } + } + + #region GraphicObject overrides + [XmlAttributeAttribute()][DefaultValue(-1)] + public override int Width { + get { return base.Width; } + set { base.Width = value; } + } + [XmlAttributeAttribute()][DefaultValue(-1)] + public override int Height { + get { return base.Height; } + set { base.Height = value; } + } + [XmlAttributeAttribute()][DefaultValue(2)] + public override int Margin { + get { return base.Margin; } + set { base.Margin = value; } + } + + protected override Size measureRawSize() + { + Size size; + + 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 (); + + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + + te = new TextExtents(); + + foreach (string s in lines) { + string l = s.Replace("\t", new String (' ', Interface.TabSize)); + +#if _WIN32 || _WIN64 + TextExtents tmp = gr.TextExtents(str.ToUtf8()); +#elif __linux__ + TextExtents tmp = gr.TextExtents (l); +#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 size;; + } + protected override void onDraw (Context gr) + { + base.onDraw (gr); + + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + + gr.Antialias = Antialias.Subpixel; + //gr.FontOptions.Antialias = Antialias.Subpixel; + //gr.FontOptions.HintMetrics = HintMetrics.On; + + rText = new Rectangle(measureRawSize()); + rText.Width -= 2 * Margin; + rText.Height -= 2 * Margin; + + widthRatio = 1f; + heightRatio = 1f; + + Rectangle cb = ClientRectangle; + + //ignore text alignment if size to content = true + //or if text size is larger than client bounds + if (Bounds.Size < 0 || rText.Width > cb.Width) + { + rText.X = cb.X; + rText.Y = cb.Y; + }else { + + switch (TextAlignment) + { + case Alignment.None: + break; + case Alignment.TopLeft: //ok + rText.X = cb.X; + rText.Y = cb.Y; + break; + case Alignment.TopCenter: //ok + rText.Y = cb.Y; + rText.X = cb.X + cb.Width / 2 - rText.Width / 2; + break; + case Alignment.TopRight: //ok + rText.X = cb.Right - rText.Width; + rText.Y = cb.Y; + break; + case Alignment.TopStretch://ok + heightRatio = widthRatio = (float)cb.Width / rText.Width; + rText.X = cb.X; + rText.Y = cb.Y; + rText.Width = cb.Width; + rText.Height = (int)(rText.Height * heightRatio); + break; + case Alignment.LeftCenter://ok + rText.X = cb.X; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + case Alignment.LeftStretch://ok + heightRatio = widthRatio = (float)cb.Height / rText.Height; + rText.X = cb.X; + rText.Y = cb.Y; + rText.Height = cb.Height; + rText.Width = (int)(widthRatio * cb.Width); + break; + case Alignment.RightCenter://ok + rText.X = cb.X + cb.Width - rText.Width; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + case Alignment.RightStretch://ok + heightRatio = widthRatio = (float)cb.Height / rText.Height; + rText.Height = cb.Height; + rText.Width = (int)(widthRatio * cb.Width); + rText.X = cb.X; + rText.Y = cb.Y; + break; + case Alignment.BottomCenter://ok + rText.X = cb.Width / 2 - rText.Width / 2; + rText.Y = cb.Height - rText.Height; + break; + case Alignment.BottomStretch://ok + heightRatio = widthRatio = (float)cb.Width / rText.Width; + rText.Width = cb.Width; + rText.Height = (int)(rText.Height * heightRatio); + rText.Y = cb.Bottom - rText.Height; + rText.X = cb.X; + break; + case Alignment.BottomLeft://ok + rText.X = cb.X; + rText.Y = cb.Bottom - rText.Height; + break; + case Alignment.BottomRight://ok + rText.Y = cb.Bottom - rText.Height; + rText.X = cb.Right - rText.Width; + break; + case Alignment.Center://ok + rText.X = cb.X + cb.Width / 2 - rText.Width / 2; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + case Alignment.Fit://ok, peut être mieu aligné + widthRatio = (float)cb.Width / rText.Width; + heightRatio = (float)cb.Height / rText.Height; + rText = cb; + break; + case Alignment.HorizontalStretch://ok + heightRatio = widthRatio = (float)cb.Width / rText.Width; + rText.Width = cb.Width; + rText.Height = (int)(heightRatio * rText.Height); + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + rText.X = cb.X; + break; + case Alignment.VerticalStretch://ok + heightRatio = widthRatio = (float)cb.Height / rText.Height; + rText.Height = cb.Height; + rText.Width = (int)(widthRatio * rText.Width); + rText.X = cb.X + cb.Width / 2 - rText.Width / 2; + rText.Y = cb.Y; + break; + default: + break; + } + } + + gr.FontMatrix = new Matrix(widthRatio * Font.Size, 0, 0, heightRatio * Font.Size, 0, 0); + + + int curLineCount = 0; + for (int i = 0;i < lines.Count;i++) { + string l = lines [i].Replace ("\t", new String (' ', Interface.TabSize)); + List<string> wl = new List<string> (); + int lineLength = (int)gr.TextExtents (l).XAdvance; + + if (wordWrap && lineLength > cb.Width) { + string tmpLine = ""; + int curChar = 0; + while (curChar < l.Length) { + tmpLine += l [curChar]; + if ((int)gr.TextExtents (tmpLine).XAdvance > cb.Width) { + tmpLine = tmpLine.Remove (tmpLine.Length - 1); + wl.Add (tmpLine); + tmpLine = ""; + continue; + } + curChar++; + } + wl.Add (tmpLine); + } else + wl.Add (l); + + foreach (string ll in wl) { + lineLength = (int)gr.TextExtents (ll).XAdvance; + + + if (string.IsNullOrWhiteSpace (ll)) { + curLineCount++; + continue; + } + + gr.SetSourceColor (Foreground); + gr.MoveTo (rText.X, rText.Y + fe.Ascent + fe.Height * curLineCount); + + #if _WIN32 || _WIN64 + gr.ShowText(ll.ToUtf8()); + #elif __linux__ + gr.ShowText (ll); + #endif + gr.Fill (); + + curLineCount++; + + } + } + } + #endregion + } +} diff --git a/src/GraphicObjects/VerticalStack.cs b/src/GraphicObjects/VerticalStack.cs index b23e6813..afd26429 100644 --- a/src/GraphicObjects/VerticalStack.cs +++ b/src/GraphicObjects/VerticalStack.cs @@ -1,25 +1,25 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Crow
-{
- public class VerticalStack : GenericStack
- {
- public VerticalStack()
- : base()
- {
- Orientation = Crow.Orientation.Vertical;
- }
-
- [System.Xml.Serialization.XmlIgnore]
- public override Orientation Orientation
- {
- get { return Orientation.Vertical; }
- //set { }
- }
-
-
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Crow +{ + public class VerticalStack : GenericStack + { + public VerticalStack() + : base() + { + Orientation = Crow.Orientation.Vertical; + } + + [System.Xml.Serialization.XmlIgnore] + public override Orientation Orientation + { + get { return Orientation.Vertical; } + //set { } + } + + + } +} diff --git a/src/GraphicObjects/WrappedWidgetGroup.cs b/src/GraphicObjects/WrappedWidgetGroup.cs index afd54e6c..fa033b5e 100755 --- a/src/GraphicObjects/WrappedWidgetGroup.cs +++ b/src/GraphicObjects/WrappedWidgetGroup.cs @@ -1,154 +1,154 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Drawing;
-using OpenTK.Graphics.OpenGL;
-using System.Diagnostics;
-
-namespace go
-{
- public class WrappedWidgetGroup : Group
- {
-
- public int widgetSpacing = 2;
-
- public Orientation Orientation = Orientation.Horizontal;
-
-
- public WrappedWidgetGroup()
- : base()
- {
- BorderWidth = 0;
- }
-
- int currentXForWidget = 0;
- int currentYForWidget = 0;
-
- int highestWidget = 0;
- int largestWidget = 0;
-
-
- public override void UpdateLayout()
- {
- //while (!layoutIsValid)
- //{
- //if (!(sizeIsValid && positionIsValid))
- base.UpdateLayout();
-
- //if (!base.layoutIsValid)
- // return;
-
- currentXForWidget = ClientRectangle.X;
- currentYForWidget = ClientRectangle.Y;
-
- highestWidget = 0;
- largestWidget = 0;
-
- Rectangle contentBounds = Rectangle.Zero;
-
- GraphicObject[] widgets = new GraphicObject[Children.Count];
- Children.CopyTo(widgets);
- foreach (GraphicObject w in widgets)
- {
- if (w.renderBounds.Width > largestWidget)
- largestWidget = w.renderBounds.Width;
- if (w.renderBounds.Height > highestWidget)
- highestWidget = w.renderBounds.Height;
-
- if (!enoughtSpaceForWidget(w))
- advance(w);
-
- if (enoughtSpaceForWidget(w))
- {
- w.renderBounds.X = currentXForWidget;
- w.renderBounds.Y = currentYForWidget;
-
- w.positionIsValid = true;
-
- contentBounds += w.renderBounds;
-
- advance(w);
- }
- else
- break;
- }
-
- contentBounds.Width += BorderWidth + Margin;
- contentBounds.Height += BorderWidth + Margin;
-
- if (SizeToContent)
- renderBounds.Size = contentBounds.Size;
- else if (VerticalScrolling)
- renderBounds.Size = new Size(renderBounds.Size.Width, contentBounds.Size.Height);
- else if (HorizontalScrolling)
- renderBounds.Size = new Size(contentBounds.Size.Width, renderBounds.Size.Height);
-
- if (layoutIsValid)
- registerForRedraw();
- }
-
-
- bool enoughtSpaceForWidget(GraphicObject w)
- {
- int nextXForWidget = 0;
- int nextYForWidget = 0;
-
- if (Orientation == Orientation.Horizontal)
- nextXForWidget = currentXForWidget + w.renderBounds.Width;
- else
- nextYForWidget = nextYForWidget + w.renderBounds.Height;
-
- if (!SizeToContent)
- {
- if (nextXForWidget > ClientRectangle.Right && !HorizontalScrolling)
- return false;
- if (currentYForWidget > ClientRectangle.Bottom && !VerticalScrolling)
- return false;
- }
- return true;
- }
- void advance(GraphicObject w)
- {
- if (Orientation == Orientation.Horizontal)
- {
- //if (w is LabelWidget)
- // Debugger.Break();
- currentXForWidget = currentXForWidget + widgetSpacing + w.renderBounds.Width;
- }
- else
- currentYForWidget = currentYForWidget + widgetSpacing + w.renderBounds.Height;
-
- if (!SizeToContent)
- {
- if (currentXForWidget > ClientRectangle.Right && !HorizontalScrolling)
- {
- if (Orientation == Orientation.Vertical)
- {
- //not scrolling
- }
- else
- {
- currentXForWidget = ClientRectangle.X;
- currentYForWidget += widgetSpacing + highestWidget;
- highestWidget = 0;
- }
- }
- if (currentYForWidget > ClientRectangle.Bottom && !VerticalScrolling)
- {
- if (Orientation == Orientation.Horizontal)
- {
- //not scrolling
- }
- else
- {
- currentXForWidget += widgetSpacing + largestWidget;
- currentYForWidget = ClientRectangle.Y;
- largestWidget = 0;
- }
-
- }
- }
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Drawing; +using OpenTK.Graphics.OpenGL; +using System.Diagnostics; + +namespace go +{ + public class WrappedWidgetGroup : Group + { + + public int widgetSpacing = 2; + + public Orientation Orientation = Orientation.Horizontal; + + + public WrappedWidgetGroup() + : base() + { + BorderWidth = 0; + } + + int currentXForWidget = 0; + int currentYForWidget = 0; + + int highestWidget = 0; + int largestWidget = 0; + + + public override void UpdateLayout() + { + //while (!layoutIsValid) + //{ + //if (!(sizeIsValid && positionIsValid)) + base.UpdateLayout(); + + //if (!base.layoutIsValid) + // return; + + currentXForWidget = ClientRectangle.X; + currentYForWidget = ClientRectangle.Y; + + highestWidget = 0; + largestWidget = 0; + + Rectangle contentBounds = Rectangle.Zero; + + GraphicObject[] widgets = new GraphicObject[Children.Count]; + Children.CopyTo(widgets); + foreach (GraphicObject w in widgets) + { + if (w.renderBounds.Width > largestWidget) + largestWidget = w.renderBounds.Width; + if (w.renderBounds.Height > highestWidget) + highestWidget = w.renderBounds.Height; + + if (!enoughtSpaceForWidget(w)) + advance(w); + + if (enoughtSpaceForWidget(w)) + { + w.renderBounds.X = currentXForWidget; + w.renderBounds.Y = currentYForWidget; + + w.positionIsValid = true; + + contentBounds += w.renderBounds; + + advance(w); + } + else + break; + } + + contentBounds.Width += BorderWidth + Margin; + contentBounds.Height += BorderWidth + Margin; + + if (SizeToContent) + renderBounds.Size = contentBounds.Size; + else if (VerticalScrolling) + renderBounds.Size = new Size(renderBounds.Size.Width, contentBounds.Size.Height); + else if (HorizontalScrolling) + renderBounds.Size = new Size(contentBounds.Size.Width, renderBounds.Size.Height); + + if (layoutIsValid) + registerForRedraw(); + } + + + bool enoughtSpaceForWidget(GraphicObject w) + { + int nextXForWidget = 0; + int nextYForWidget = 0; + + if (Orientation == Orientation.Horizontal) + nextXForWidget = currentXForWidget + w.renderBounds.Width; + else + nextYForWidget = nextYForWidget + w.renderBounds.Height; + + if (!SizeToContent) + { + if (nextXForWidget > ClientRectangle.Right && !HorizontalScrolling) + return false; + if (currentYForWidget > ClientRectangle.Bottom && !VerticalScrolling) + return false; + } + return true; + } + void advance(GraphicObject w) + { + if (Orientation == Orientation.Horizontal) + { + //if (w is LabelWidget) + // Debugger.Break(); + currentXForWidget = currentXForWidget + widgetSpacing + w.renderBounds.Width; + } + else + currentYForWidget = currentYForWidget + widgetSpacing + w.renderBounds.Height; + + if (!SizeToContent) + { + if (currentXForWidget > ClientRectangle.Right && !HorizontalScrolling) + { + if (Orientation == Orientation.Vertical) + { + //not scrolling + } + else + { + currentXForWidget = ClientRectangle.X; + currentYForWidget += widgetSpacing + highestWidget; + highestWidget = 0; + } + } + if (currentYForWidget > ClientRectangle.Bottom && !VerticalScrolling) + { + if (Orientation == Orientation.Horizontal) + { + //not scrolling + } + else + { + currentXForWidget += widgetSpacing + largestWidget; + currentYForWidget = ClientRectangle.Y; + largestWidget = 0; + } + + } + } + } + } +} |