namespace Crow
{
- public enum Orientation
- {
- Horizontal,
- Vertical
- }
-
- public enum Alignment
- {
- Top = 0x01,
- Left = 0x02,
- TopLeft = 0x03,
- Right = 0x04,
- TopRight = 0x05,
- Bottom = 0x08,
- BottomLeft = 0x0a,
- BottomRight = 0x0c,
- Center = 0x10,
- Undefined = 0x40
- }
- public enum TextAlignment
- {
- Left,
- Right,
- Center,
- Justify
- }
- public enum HorizontalAlignment
- {
- Left,
- Right,
- Center,
- }
- public enum VerticalAlignment
- {
- Top,
- Bottom,
- Center,
- }
- public enum MouseCursor
- {
- arrow,
- base_arrow_down,
- base_arrow_up,
- boat,
- bottom_left_corner,
- bottom_right_corner,
- bottom_side,
- bottom_tee,
- center_ptr,
- circle,
- cross,
- cross_reverse,
- crosshair,
- dot,
- dot_box_mask,
- double_arrow,
- draft_large,
- draft_small,
- draped_box,
- exchange,
- fleur,
- gumby,
- hand,
- hand1,
- hand2,
- help,
- ibeam,
- left_ptr,
- left_ptr_watch,
- left_side,
- left_tee,
- ll_angle,
- lr_angle,
- move,
- pencil,
- pirate,
- plus,
- question_arrow,
- right_ptr,
- right_side,
- right_tee,
- sailboat,
- sb_down_arrow,
- sb_h_double_arrow,
- sb_left_arrow,
- sb_right_arrow,
- sb_up_arrow,
- sb_v_double_arrow,
- shuttle,
- sizing,
- target,
- tcross,
- top_left_arrow,
- top_left_corner,
- top_right_corner,
- top_side,
- top_tee,
- trek,
- ul_angle,
- ur_angle,
- watch,
- X_cursor,
- xterm,
- }
- /// <summary>
- /// Cursor shape use in Sliders
- /// </summary>
- public enum CursorType
- {
- /// <summary>Only Background of cursor will be drawm, you may use a bmp, svg, or shape as background for custom shape.</summary>
- None,
- Rectangle,
- Circle,
- Pentagone
- }
- /// <summary>
- /// Color component used in color widgets
- /// </summary>
- public enum ColorComponent
- {
- Red,
- Green,
- Blue,
- Alpha,
- Hue,
- Saturation,
- Value
- }
+
}
+++ /dev/null
-// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Collections.Generic;
-
-namespace Crow
-{
- public class ListChangedEventArg : EventArgs
- {
- public int Index;
- public object Element;
- public ListChangedEventArg (int index, object element)
- {
- Index = index;
- Element = element;
- }
- }
- public class ListClearEventArg : EventArgs
- {
- public IEnumerable<object> Elements;
- public ListClearEventArg (IEnumerable<object> elements) {
- Elements = elements;
- }
- }
-}
+++ /dev/null
-// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-
-namespace Crow
-{
- /// <summary>
- /// Arguments for the ValueChange event used for Binding
- /// </summary>
- public class ValueChangeEventArgs: EventArgs
- {
- /// <summary>The name of the member whose value has changed</summary>
- public string MemberName;
- /// <summary>New value for that member</summary>
- public object NewValue;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="T:Crow.ValueChangeEventArgs"/> class.
- /// </summary>
- /// <param name="_memberName">Member name.</param>
- /// <param name="_newValue">New value.</param>
- public ValueChangeEventArgs (string _memberName, object _newValue) : base()
- {
- MemberName = _memberName;
- NewValue = _newValue;
- }
- }
-}
-
+++ /dev/null
-// Copyright (c) 2013-2021 Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using Drawing2D;
-
-namespace Crow
-{
- public enum FontStyle
- {
- Normal,
- Bold,
- Italic,
- Underlined
- }
- public class Font
- {
- #region CTOR
- public Font ()
- {
- }
- #endregion
-
- string _name = "sans";
- int _size = 10;
- FontStyle _style = FontStyle.Normal;
-
- public string Name {
- get { return _name; }
- set { _name = value; }
- }
- public int Size {
- get { return _size; }
- set { _size = value; }
- }
- public FontStyle Style {
- get { return _style; }
- set { _style = value; }
- }
-
- public FontSlant Slant {
- get{
- switch (Style) {
- case FontStyle.Italic:
- return FontSlant.Italic;
- default:
- return FontSlant.Normal;
- }
- }
- }
- public FontWeight Wheight {
- get{
- switch (Style) {
- case FontStyle.Bold:
- return FontWeight.Bold;
- default:
- return FontWeight.Normal;
- }
- }
- }
-
- #region Operators
- public static implicit operator string(Font c) => c.ToString();
-
- public static implicit operator Font(string s) => (Font)Parse(s);
- #endregion
-
- public override string ToString () =>
- _style == FontStyle.Normal ? $"{_name},{_size}" : $"{_name} {_style},{_size}";
-
- public static Font Parse(string s)
- {
- Font f = new Font ();
- ReadOnlySpan<char> tmp = s.AsSpan ().Trim ();
- if (tmp.Length > 0) {
- int ioc = tmp.IndexOf (',');
-
- if (ioc >= 0) {
- f.Size = int.Parse (tmp.Slice (ioc + 1).Trim ());
- tmp = tmp.Slice (0, ioc).TrimEnd ();
- }
-
- ioc = tmp.IndexOf (' ');
-
- if (ioc < 0)
- f.Name = tmp.ToString ();
- else {
- f.Name = tmp.Slice (0, ioc).ToString ();
- f.Style = EnumsNET.Enums.Parse<FontStyle> (tmp.Slice (ioc + 1).ToString (), true);
- }
- }
- return f;
- }
- }
-}
-
+++ /dev/null
-// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-
-namespace Crow
-{
- public interface IObservableList {
- event EventHandler<ListChangedEventArg> ListAdd;
- event EventHandler<ListChangedEventArg> ListRemove;
- event EventHandler<ListChangedEventArg> ListEdit;
- event EventHandler<ListClearEventArg> ListClear;
-
- void Insert ();
- void Remove ();
- void RaiseEdit ();
- }
-}
-
+++ /dev/null
-// Copyright (c) 2020-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-
-namespace Crow
-{
- public interface ISelectable
- {
- event EventHandler Selected;
- event EventHandler Unselected;
-
- bool IsSelected {
- get;
- set;
- }
-
- }
-}
+++ /dev/null
-// Copyright (c) 2020-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-
-namespace Crow
-{
- public interface IToggle
- {
- event EventHandler ToggleOn;
- event EventHandler ToggleOff;
- BooleanTestOnInstance IsToggleable { get; set; }
-
- bool IsToggled {
- get;
- set;
- }
-
- }
-}
+++ /dev/null
-// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.Collections.Generic;
-
-namespace Crow
-{
- /// <summary>
- /// implement `IValueChange` interface in object you want to bind to the interface.
- /// For each property updated in code, raise a value change in the container class
- /// to inform Crow binding system that the value has changed.
- /// </summary>
- public interface IValueChange
- {
- event EventHandler<ValueChangeEventArgs> ValueChanged;
- }
- /// <summary>
- /// Container for net primitive value type implementing IValueChange
- /// </summary>
- public class ValueContainer<T> : IValueChange, IEquatable<T>//, IConvertible
- {
- public event EventHandler<ValueChangeEventArgs> ValueChanged;
- T val;
- public T Value {
- get => val;
- set {
- if (EqualityComparer<T>.Default.Equals (value, val))
- return;
- val = value;
- ValueChanged?.Invoke (this, new Crow.ValueChangeEventArgs ("Value", val));
- }
- }
-
- public static implicit operator ValueContainer<T>(T v) => new ValueContainer<T> (v);
- public static implicit operator T (ValueContainer<T> v) => v.Value;
-
- public ValueContainer (T _val) { val = _val; }
-
- public bool Equals (T other) => val.Equals (other);
- public override bool Equals (object obj) => obj is ValueContainer<T> v && Equals (v);
- public override int GetHashCode () => val.GetHashCode ();
- public override string ToString () => val.ToString ();
- }
-}
-
//at the root level of the item template if the dataTest is 'typeOf'...
namespace Crow
{
- /// <summary> Test func on data, return yes if there's children </summary>
- public delegate bool BooleanTestOnInstance(object instance);
-
/// <summary>
/// Derived from Instantiator with sub data fetching facilities for hierarchical data access.
///
+++ /dev/null
-using System.Reflection;
-// Copyright (c) 2013-2019 Bruyère Jean-Philippe jp_bruyere@hotmail.com
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Collections;
-
-namespace Crow
-{
- public class ObservableList<T> : IList<T>, IObservableList, IValueChange, ICollection {
- #region IValueChange implementation
- public event EventHandler<ValueChangeEventArgs> ValueChanged;
- public virtual void NotifyValueChanged (string MemberName, object _value)
- {
- ValueChanged?.Invoke (this, new ValueChangeEventArgs (MemberName, _value));
- }
- #endregion
-
- #region IObservableList implementation
- public event EventHandler<ListChangedEventArg> ListAdd;
- public event EventHandler<ListChangedEventArg> ListRemove;
- public event EventHandler<ListChangedEventArg> ListEdit;
- public event EventHandler<ListClearEventArg> ListClear;
- #endregion
-
- List<T> items;
- public ObservableList() {
- items = new List<T>();
- }
- public ObservableList (IEnumerable<T> collection) {
- items = new List<T> (collection);
- }
-
- int selectedIndex = -1;
-
- public int SelectedIndex {
- get => selectedIndex;
- set {
- if (selectedIndex == value)
- return;
-
- if (value > Count - 1)
- selectedIndex = Count - 1;
- else
- selectedIndex = value;
-
- NotifyValueChanged ("SelectedIndex", selectedIndex);
- NotifyValueChanged ("SelectedItem", SelectedItem);
- }
- }
- public T SelectedItem {
- get => selectedIndex < 0 ? default(T) : this [selectedIndex];
- set {
- this [selectedIndex] = value;
- }
- }
-
- public int Count => items.Count;
-
- public bool IsReadOnly => false;
-
- public bool IsSynchronized => throw new NotImplementedException();
-
- public object SyncRoot => throw new NotImplementedException();
-
- public T this[int index] {
- get => items[index];
- set {
-
- if (items[index] == null) {
- if (value == null)
- return;
- }else if (items[index].Equals (value))
- return;
- Replace (items[index], value);
- }
- }
-
- public void Add (T elem) {
- items.Add (elem);
- ListAdd.Raise (this, new ListChangedEventArg (this.Count - 1, elem));
- SelectedIndex = this.Count - 1;
- }
- public void Insert (int index, T elem) {
- items.Insert (index, elem);
- ListAdd.Raise (this, new ListChangedEventArg (index, elem));
- SelectedIndex = index;
- }
- public bool Remove (T elem) {
- int idx = IndexOf (elem);
- if (idx < 0)
- return false;
- else
- items.RemoveAt (idx);
- ListRemove.Raise (this, new ListChangedEventArg (idx, elem));
- return true;
- }
- public void Clear ()
- {
- ListClearEventArg eventArg = new ListClearEventArg (this.Cast<object>());
- items.Clear ();
- ListClear.Raise (this, eventArg);
- }
- public void Remove () {
- if (selectedIndex < 0)
- return;
- RemoveAt (selectedIndex);
- SelectedIndex--;
- }
- public void Insert ()
- {
- items.Insert (selectedIndex+1, default(T));
- SelectedIndex++;
- ListAdd.Raise (this, new ListChangedEventArg (selectedIndex, SelectedItem));
- }
- public void Replace (T oldValue, T newValue) {
- int idx = IndexOf (oldValue);
- items[idx] = newValue;
- ListEdit.Raise (this, new ListChangedEventArg (idx, newValue));
- }
- public void RaiseEdit () {
- if (selectedIndex < 0)
- return;
- ListEdit.Raise (this, new ListChangedEventArg (selectedIndex, SelectedItem));
- }
-
- public void RemoveAt (int index)
- {
- items.RemoveAt (index);
- ListRemove.Raise (this, new ListChangedEventArg (index, null));
- }
- public void RaiseEditAt (int index) {
- ListEdit.Raise (this, new ListChangedEventArg (index, this[index]));
- }
-
-
- public static ObservableList<T> Parse (string str) {
- ObservableList<T> tmp = new ObservableList<T>();
- if (!string.IsNullOrEmpty (str)) {
- Type t = typeof(T);
- if (t.IsEnum) {
- foreach (string s in str.Split(';'))
- tmp.Add((T)Enum.Parse(t, s));
- } else {
- MethodInfo miParse = t.GetMethod ("Parse",
- BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder, new Type [] {typeof (string)}, null);
- if (miParse == null)
- throw new Exception ("no Parse method found for: " + t.FullName);
-
- foreach (string s in str.Split(';'))
- tmp.Add((T)miParse.Invoke (null, new object[] {s}));
- }
- }
- return tmp;
- }
-
- public int IndexOf(T item) => items.IndexOf (item);
-
- public bool Contains(T item) => items.Contains (item);
-
- public void CopyTo(T[] array, int arrayIndex) => items.CopyTo (array, arrayIndex);
-
-
- public IEnumerator<T> GetEnumerator() => items.GetEnumerator ();
-
- IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator ();
-
- public void CopyTo(Array array, int index) => items.ToArray().CopyTo (array, index);
- }
-}
-
}
Widget stretchedGO = null;
public override bool UpdateLayout (LayoutingType layoutType) {
- RegisteredLayoutings &= (~layoutType);
-
if (layoutType == LayoutingType.ArrangeChildren) {
+ RegisteredLayoutings &= (~layoutType);
//allow 1 child to have stretched size,
//this child will occupy remaining space
//if stack size policy is Fit, no child may have stretch enabled
-//
-// Grid.cs
+// Copyright (c) 2013-2025 Bruyère Jean-Philippe jp_bruyere@hotmail.com
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Diagnostics;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Xml.Serialization;
using System.ComponentModel;
namespace Crow
{
#region CTOR
protected Grid () : base(){}
- public Grid(Interface iface) : base(iface)
- {
- }
+ public Grid(Interface iface, string style = null) : base (iface, style) { }
#endregion
#region Private fields
- int _spacing;
- int _columnCount;
- int _rowCount;
+ int spacing;
+ int columnCount;
+ int rowCount;
#endregion
#region Public Properties
- [DefaultValue(2)]
- public int Spacing
- {
- get { return _spacing; }
- set { _spacing = value; }
+ [DefaultValue (2)]
+ public int Spacing {
+ get => spacing;
+ set {
+ if (spacing == value)
+ return;
+ spacing = value;
+ NotifyValueChangedAuto (spacing);
+ RegisterForLayouting (LayoutingType.ArrangeChildren);
+ }
}
[DefaultValue(2)]
public virtual int ColumnCount
{
- get { return _columnCount; }
+ get { return columnCount; }
set {
- if (_columnCount == value)
+ if (columnCount == value)
return;
- _columnCount = value;
+ columnCount = value;
NotifyValueChangedAuto (ColumnCount);
- this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+ RegisterForLayouting (LayoutingType.ArrangeChildren);
}
}
[DefaultValue(2)]
public virtual int RowCount
{
- get { return _rowCount; }
+ get { return rowCount; }
set {
- if (_rowCount == value)
+ if (rowCount == value)
return;
- _rowCount = value;
+ rowCount = value;
NotifyValueChangedAuto (RowCount);
- this.RegisterForLayouting (LayoutingType.ArrangeChildren);
+ RegisterForLayouting (LayoutingType.ArrangeChildren);
}
}
- public virtual int CaseWidth {
- get => (Slot.Width - (ColumnCount - 1) * Spacing) / ColumnCount;
- }
- public virtual int CaseHeight {
- get => (Slot.Height - (RowCount - 1) * Spacing) / RowCount;
- }
-
+ public virtual int CaseWidth => (Slot.Width - (ColumnCount - 1) * Spacing) / ColumnCount;
+ public virtual int CaseHeight => (Slot.Height - (RowCount - 1) * Spacing) / RowCount;
#endregion
#region Widget Overrides
public override void ChildrenLayoutingConstraints (ILayoutable layoutable, ref LayoutingType layoutType)
{
//Prevent child repositionning
- layoutType &= (~LayoutingType.Positioning);
+ layoutType &= (~LayoutingType.Sizing);
}
- public override bool ArrangeChildren { get { return true; } }
+ public override bool ArrangeChildren => true;
public virtual void ComputeChildrenPositions()
{
int slotWidth = CaseWidth;
Widget c = Children [idx];
if (!c.IsVisible)
continue;
- c.Slot.X = curX * (slotWidth + Spacing);
- c.Slot.Y = curY * (slotHeight + Spacing);
- //c.Slot.Width = slotWidth;
- //c.Slot.Height = slotHeight;
+ int x = curX * (slotWidth + Spacing);
+ if (c.Slot.X != x) {
+ c.Slot.X = x;
+ c.OnLayoutChanges (LayoutingType.X);
+ c.LastSlots.X = c.Slot.X;
+ IsDirty = true;
+ }
+ int y = curY * (slotHeight + Spacing);
+ if (c.Slot.Y != y) {
+ c.Slot.Y = y;
+ c.OnLayoutChanges (LayoutingType.Y);
+ c.LastSlots.Y = c.Slot.Y;
+ IsDirty = true;
+ }
}
}
IsDirty = true;
}
- public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
- {
- //base.OnChildLayoutChanges (sender, arg);
- }
-
- public override bool UpdateLayout (LayoutingType layoutType)
+ public override void RegisterForLayouting(LayoutingType layoutType)
+ {
+ base.RegisterForLayouting(layoutType);
+ }
+ public override void OnLayoutChanges(LayoutingType layoutType)
+ {
+ base.OnLayoutChanges(layoutType);
+ }
+ public override void OnChildLayoutChanges(object sender, LayoutingEventArgs arg)
+ {
+ base.OnChildLayoutChanges(sender, arg);
+ }
+
+ public override bool UpdateLayout (LayoutingType layoutType)
{
- RegisteredLayoutings &= (~layoutType);
-
if (layoutType == LayoutingType.ArrangeChildren) {
+ RegisteredLayoutings &= (~layoutType);
ComputeChildrenPositions ();
-
- //if no layouting remains in queue for item, registre for redraw
- if (RegisteredLayoutings == LayoutingType.None && IsDirty)
- IFace.EnqueueForRepaint (this);
-
return true;
}
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
namespace Crow
{
/// <summary>
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using static Crow.Logger;
+
namespace Crow
{
/// <summary>
public override bool UpdateLayout (LayoutingType layoutType)
{
- RegisteredLayoutings &= (~layoutType);
-
if (layoutType == LayoutingType.ArrangeChildren) {
+ RegisteredLayoutings &= (~layoutType);
if ((RequiredLayoutings & LayoutingType.Sizing) != 0)
return false;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
+using Drawing2D;
namespace Crow
{
--- /dev/null
+// Copyright (c) 2018-2022 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+
+ public enum Orientation
+ {
+ Horizontal,
+ Vertical
+ }
+
+ public enum Alignment
+ {
+ Top = 0x01,
+ Left = 0x02,
+ TopLeft = 0x03,
+ Right = 0x04,
+ TopRight = 0x05,
+ Bottom = 0x08,
+ BottomLeft = 0x0a,
+ BottomRight = 0x0c,
+ Center = 0x10,
+ Undefined = 0x40
+ }
+ public enum TextAlignment
+ {
+ Left,
+ Right,
+ Center,
+ Justify
+ }
+ public enum HorizontalAlignment
+ {
+ Left,
+ Right,
+ Center,
+ }
+ public enum VerticalAlignment
+ {
+ Top,
+ Bottom,
+ Center,
+ }
+ public enum MouseCursor
+ {
+ arrow,
+ base_arrow_down,
+ base_arrow_up,
+ boat,
+ bottom_left_corner,
+ bottom_right_corner,
+ bottom_side,
+ bottom_tee,
+ center_ptr,
+ circle,
+ cross,
+ cross_reverse,
+ crosshair,
+ dot,
+ dot_box_mask,
+ double_arrow,
+ draft_large,
+ draft_small,
+ draped_box,
+ exchange,
+ fleur,
+ gumby,
+ hand,
+ hand1,
+ hand2,
+ help,
+ ibeam,
+ left_ptr,
+ left_ptr_watch,
+ left_side,
+ left_tee,
+ ll_angle,
+ lr_angle,
+ move,
+ pencil,
+ pirate,
+ plus,
+ question_arrow,
+ right_ptr,
+ right_side,
+ right_tee,
+ sailboat,
+ sb_down_arrow,
+ sb_h_double_arrow,
+ sb_left_arrow,
+ sb_right_arrow,
+ sb_up_arrow,
+ sb_v_double_arrow,
+ shuttle,
+ sizing,
+ target,
+ tcross,
+ top_left_arrow,
+ top_left_corner,
+ top_right_corner,
+ top_side,
+ top_tee,
+ trek,
+ ul_angle,
+ ur_angle,
+ watch,
+ X_cursor,
+ xterm,
+ }
+ /// <summary>
+ /// Cursor shape use in Sliders
+ /// </summary>
+ public enum CursorType
+ {
+ /// <summary>Only Background of cursor will be drawm, you may use a bmp, svg, or shape as background for custom shape.</summary>
+ None,
+ Rectangle,
+ Circle,
+ Pentagone
+ }
+ /// <summary>
+ /// Color component used in color widgets
+ /// </summary>
+ public enum ColorComponent
+ {
+ Red,
+ Green,
+ Blue,
+ Alpha,
+ Hue,
+ Saturation,
+ Value
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using Drawing2D;
+
+namespace Crow
+{
+ public enum FontStyle
+ {
+ Normal,
+ Bold,
+ Italic,
+ Underlined
+ }
+ public class Font
+ {
+ #region CTOR
+ public Font ()
+ {
+ }
+ #endregion
+
+ string _name = "sans";
+ int _size = 10;
+ FontStyle _style = FontStyle.Normal;
+
+ public string Name {
+ get { return _name; }
+ set { _name = value; }
+ }
+ public int Size {
+ get { return _size; }
+ set { _size = value; }
+ }
+ public FontStyle Style {
+ get { return _style; }
+ set { _style = value; }
+ }
+
+ public FontSlant Slant {
+ get{
+ switch (Style) {
+ case FontStyle.Italic:
+ return FontSlant.Italic;
+ default:
+ return FontSlant.Normal;
+ }
+ }
+ }
+ public FontWeight Wheight {
+ get{
+ switch (Style) {
+ case FontStyle.Bold:
+ return FontWeight.Bold;
+ default:
+ return FontWeight.Normal;
+ }
+ }
+ }
+
+ #region Operators
+ public static implicit operator string(Font c) => c.ToString();
+
+ public static implicit operator Font(string s) => (Font)Parse(s);
+ #endregion
+
+ public override string ToString () =>
+ _style == FontStyle.Normal ? $"{_name},{_size}" : $"{_name} {_style},{_size}";
+
+ public static Font Parse(string s)
+ {
+ Font f = new Font ();
+ ReadOnlySpan<char> tmp = s.AsSpan ().Trim ();
+ if (tmp.Length > 0) {
+ int ioc = tmp.IndexOf (',');
+
+ if (ioc >= 0) {
+ f.Size = int.Parse (tmp.Slice (ioc + 1).Trim ());
+ tmp = tmp.Slice (0, ioc).TrimEnd ();
+ }
+
+ ioc = tmp.IndexOf (' ');
+
+ if (ioc < 0)
+ f.Name = tmp.ToString ();
+ else {
+ f.Name = tmp.Slice (0, ioc).ToString ();
+ f.Style = EnumsNET.Enums.Parse<FontStyle> (tmp.Slice (ioc + 1).ToString (), true);
+ }
+ }
+ return f;
+ }
+ }
+}
+
namespace Crow
{
+ /// <summary> Test func on data, return yes if there's children </summary>
+ public delegate bool BooleanTestOnInstance(object instance);
public class XmlIgnoreAttribute : Attribute
{
}
--- /dev/null
+// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+ public interface IObservableList {
+ event EventHandler<ListChangedEventArg> ListAdd;
+ event EventHandler<ListChangedEventArg> ListRemove;
+ event EventHandler<ListChangedEventArg> ListEdit;
+ event EventHandler<ListClearEventArg> ListClear;
+
+ void Insert ();
+ void Remove ();
+ void RaiseEdit ();
+ }
+}
+
--- /dev/null
+// Copyright (c) 2020-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+ public interface ISelectable
+ {
+ event EventHandler Selected;
+ event EventHandler Unselected;
+
+ bool IsSelected {
+ get;
+ set;
+ }
+
+ }
+}
--- /dev/null
+// Copyright (c) 2020-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+ public interface IToggle
+ {
+ event EventHandler ToggleOn;
+ event EventHandler ToggleOff;
+ BooleanTestOnInstance IsToggleable { get; set; }
+
+ bool IsToggled {
+ get;
+ set;
+ }
+
+ }
+}
--- /dev/null
+// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+
+namespace Crow
+{
+ /// <summary>
+ /// implement `IValueChange` interface in object you want to bind to the interface.
+ /// For each property updated in code, raise a value change in the container class
+ /// to inform Crow binding system that the value has changed.
+ /// </summary>
+ public interface IValueChange
+ {
+ event EventHandler<ValueChangeEventArgs> ValueChanged;
+ }
+ /// <summary>
+ /// Container for net primitive value type implementing IValueChange
+ /// </summary>
+ public class ValueContainer<T> : IValueChange, IEquatable<T>//, IConvertible
+ {
+ public event EventHandler<ValueChangeEventArgs> ValueChanged;
+ T val;
+ public T Value {
+ get => val;
+ set {
+ if (EqualityComparer<T>.Default.Equals (value, val))
+ return;
+ val = value;
+ ValueChanged?.Invoke (this, new Crow.ValueChangeEventArgs ("Value", val));
+ }
+ }
+
+ public static implicit operator ValueContainer<T>(T v) => new ValueContainer<T> (v);
+ public static implicit operator T (ValueContainer<T> v) => v.Value;
+
+ public ValueContainer (T _val) { val = _val; }
+
+ public bool Equals (T other) => val.Equals (other);
+ public override bool Equals (object obj) => obj is ValueContainer<T> v && Equals (v);
+ public override int GetHashCode () => val.GetHashCode ();
+ public override string ToString () => val.ToString ();
+ }
+}
+
--- /dev/null
+// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+
+namespace Crow
+{
+ public class ListChangedEventArg : EventArgs
+ {
+ public int Index;
+ public object Element;
+ public ListChangedEventArg (int index, object element)
+ {
+ Index = index;
+ Element = element;
+ }
+ }
+ public class ListClearEventArg : EventArgs
+ {
+ public IEnumerable<object> Elements;
+ public ListClearEventArg (IEnumerable<object> elements) {
+ Elements = elements;
+ }
+ }
+}
--- /dev/null
+using System.Reflection;
+// Copyright (c) 2013-2019 Bruyère Jean-Philippe jp_bruyere@hotmail.com
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Collections;
+
+namespace Crow
+{
+ public class ObservableList<T> : IList<T>, IObservableList, IValueChange, ICollection {
+ #region IValueChange implementation
+ public event EventHandler<ValueChangeEventArgs> ValueChanged;
+ public virtual void NotifyValueChanged (string MemberName, object _value)
+ {
+ ValueChanged?.Invoke (this, new ValueChangeEventArgs (MemberName, _value));
+ }
+ #endregion
+
+ #region IObservableList implementation
+ public event EventHandler<ListChangedEventArg> ListAdd;
+ public event EventHandler<ListChangedEventArg> ListRemove;
+ public event EventHandler<ListChangedEventArg> ListEdit;
+ public event EventHandler<ListClearEventArg> ListClear;
+ #endregion
+
+ List<T> items;
+ public ObservableList() {
+ items = new List<T>();
+ }
+ public ObservableList (IEnumerable<T> collection) {
+ items = new List<T> (collection);
+ }
+
+ int selectedIndex = -1;
+
+ public int SelectedIndex {
+ get => selectedIndex;
+ set {
+ if (selectedIndex == value)
+ return;
+
+ if (value > Count - 1)
+ selectedIndex = Count - 1;
+ else
+ selectedIndex = value;
+
+ NotifyValueChanged ("SelectedIndex", selectedIndex);
+ NotifyValueChanged ("SelectedItem", SelectedItem);
+ }
+ }
+ public T SelectedItem {
+ get => selectedIndex < 0 ? default(T) : this [selectedIndex];
+ set {
+ this [selectedIndex] = value;
+ }
+ }
+
+ public int Count => items.Count;
+
+ public bool IsReadOnly => false;
+
+ public bool IsSynchronized => throw new NotImplementedException();
+
+ public object SyncRoot => throw new NotImplementedException();
+
+ public T this[int index] {
+ get => items[index];
+ set {
+
+ if (items[index] == null) {
+ if (value == null)
+ return;
+ }else if (items[index].Equals (value))
+ return;
+ Replace (items[index], value);
+ }
+ }
+
+ public void Add (T elem) {
+ items.Add (elem);
+ ListAdd.Raise (this, new ListChangedEventArg (this.Count - 1, elem));
+ SelectedIndex = this.Count - 1;
+ }
+ public void Insert (int index, T elem) {
+ items.Insert (index, elem);
+ ListAdd.Raise (this, new ListChangedEventArg (index, elem));
+ SelectedIndex = index;
+ }
+ public bool Remove (T elem) {
+ int idx = IndexOf (elem);
+ if (idx < 0)
+ return false;
+ else
+ items.RemoveAt (idx);
+ ListRemove.Raise (this, new ListChangedEventArg (idx, elem));
+ return true;
+ }
+ public void Clear ()
+ {
+ ListClearEventArg eventArg = new ListClearEventArg (this.Cast<object>());
+ items.Clear ();
+ ListClear.Raise (this, eventArg);
+ }
+ public void Remove () {
+ if (selectedIndex < 0)
+ return;
+ RemoveAt (selectedIndex);
+ SelectedIndex--;
+ }
+ public void Insert ()
+ {
+ items.Insert (selectedIndex+1, default(T));
+ SelectedIndex++;
+ ListAdd.Raise (this, new ListChangedEventArg (selectedIndex, SelectedItem));
+ }
+ public void Replace (T oldValue, T newValue) {
+ int idx = IndexOf (oldValue);
+ items[idx] = newValue;
+ ListEdit.Raise (this, new ListChangedEventArg (idx, newValue));
+ }
+ public void RaiseEdit () {
+ if (selectedIndex < 0)
+ return;
+ ListEdit.Raise (this, new ListChangedEventArg (selectedIndex, SelectedItem));
+ }
+
+ public void RemoveAt (int index)
+ {
+ items.RemoveAt (index);
+ ListRemove.Raise (this, new ListChangedEventArg (index, null));
+ }
+ public void RaiseEditAt (int index) {
+ ListEdit.Raise (this, new ListChangedEventArg (index, this[index]));
+ }
+
+
+ public static ObservableList<T> Parse (string str) {
+ ObservableList<T> tmp = new ObservableList<T>();
+ if (!string.IsNullOrEmpty (str)) {
+ Type t = typeof(T);
+ if (t.IsEnum) {
+ foreach (string s in str.Split(';'))
+ tmp.Add((T)Enum.Parse(t, s));
+ } else {
+ MethodInfo miParse = t.GetMethod ("Parse",
+ BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder, new Type [] {typeof (string)}, null);
+ if (miParse == null)
+ throw new Exception ("no Parse method found for: " + t.FullName);
+
+ foreach (string s in str.Split(';'))
+ tmp.Add((T)miParse.Invoke (null, new object[] {s}));
+ }
+ }
+ return tmp;
+ }
+
+ public int IndexOf(T item) => items.IndexOf (item);
+
+ public bool Contains(T item) => items.Contains (item);
+
+ public void CopyTo(T[] array, int arrayIndex) => items.CopyTo (array, arrayIndex);
+
+
+ public IEnumerator<T> GetEnumerator() => items.GetEnumerator ();
+
+ IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator ();
+
+ public void CopyTo(Array array, int index) => items.ToArray().CopyTo (array, index);
+ }
+}
+
--- /dev/null
+// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace Crow
+{
+ /// <summary>
+ /// Arguments for the ValueChange event used for Binding
+ /// </summary>
+ public class ValueChangeEventArgs: EventArgs
+ {
+ /// <summary>The name of the member whose value has changed</summary>
+ public string MemberName;
+ /// <summary>New value for that member</summary>
+ public object NewValue;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:Crow.ValueChangeEventArgs"/> class.
+ /// </summary>
+ /// <param name="_memberName">Member name.</param>
+ /// <param name="_newValue">New value.</param>
+ public ValueChangeEventArgs (string _memberName, object _newValue) : base()
+ {
+ MemberName = _memberName;
+ NewValue = _newValue;
+ }
+ }
+}
+
-<Grid ColumnCount="2" RowCount="2">
- <Label/>
- <Label/>
- <Label/>
- <Label/>
+<Grid ColumnCount="3" RowCount="3" Width="Stretched" Height="Stretched" Background="Green">
+ <Label HorizontalAlignment="Right"/>
+ <Label HorizontalAlignment="Right"/>
+ <Label VerticalAlignment="Top"/>
+ <Label Background="RebeccaPurple"/>
</Grid>
\ No newline at end of file