diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-04-15 05:33:39 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-04-15 12:48:08 +0200 |
| commit | 5b2f9d9b576f1009704d6d72a082c5b125699bcc (patch) | |
| tree | 034aba09a978042356f6a0a77d074aa53f622f6c | |
| parent | dad50038e364dda92e2ab5d4790f2138ae5b3909 (diff) | |
save commit to find bug
| -rw-r--r-- | Crow/Templates/DefaultTableHeaderCell.template | 2 | ||||
| -rw-r--r-- | Crow/Templates/MenuItem.template | 2 | ||||
| -rw-r--r-- | Crow/src/IML/CompilerServices.cs | 8 | ||||
| -rw-r--r-- | Crow/src/IML/Node.cs | 2 | ||||
| -rw-r--r-- | Crow/src/ItemTemplate.cs | 4 | ||||
| -rw-r--r-- | Crow/src/Widgets/Group.cs | 371 | ||||
| -rw-r--r-- | Crow/src/Widgets/GroupBase.cs | 302 | ||||
| -rw-r--r-- | Crow/src/Widgets/Table copy.cs | 259 | ||||
| -rw-r--r-- | Crow/src/Widgets/Table.cs | 343 | ||||
| -rw-r--r-- | Crow/src/Widgets/TableRow copy.cs | 321 | ||||
| -rw-r--r-- | Crow/src/Widgets/TableRow.cs | 278 | ||||
| -rw-r--r-- | Crow/src/Widgets/Widget.cs | 33 |
12 files changed, 1368 insertions, 557 deletions
diff --git a/Crow/Templates/DefaultTableHeaderCell.template b/Crow/Templates/DefaultTableHeaderCell.template new file mode 100644 index 00000000..0bb5368b --- /dev/null +++ b/Crow/Templates/DefaultTableHeaderCell.template @@ -0,0 +1,2 @@ +<?xml version="1.0"?> +<Label RootDataLevel="true" Style="TableHeaderLabel" Text="{Caption}" Width="{Width}"/>
\ No newline at end of file diff --git a/Crow/Templates/MenuItem.template b/Crow/Templates/MenuItem.template index d5b39dd4..96adbd1e 100644 --- a/Crow/Templates/MenuItem.template +++ b/Crow/Templates/MenuItem.template @@ -1,7 +1,7 @@ <?xml version="1.0"?> <ListItem> <Popper Font="{./Font}" Caption="{./Caption}" Background="{./Background}" PopDirection="{./PopDirection}" - Foreground = "{./Foreground}" CanPop="{./HasChildren}" + Foreground = "{./Foreground}" IsPopped="{²./IsOpened}" PopWidth="{./PopWidth}" PopHeight="{./PopHeight}"> <Template> <CheckBox IsChecked="{²./IsPopped}" Caption="{./Caption}" Background="{./Background}" Foreground="{./Foreground}"> diff --git a/Crow/src/IML/CompilerServices.cs b/Crow/src/IML/CompilerServices.cs index 644902f0..8d63bb8d 100644 --- a/Crow/src/IML/CompilerServices.cs +++ b/Crow/src/IML/CompilerServices.cs @@ -103,8 +103,8 @@ namespace Crow.IML #region tree handling methods internal static FieldInfo fiChild = typeof(PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic); internal static MethodInfo miSetChild = typeof (Container).GetMethod ("SetChild"); - internal static MethodInfo miAddChild = typeof (Group).GetMethod ("AddChild"); - internal static FieldInfo fiChildren = typeof(Group).GetField ("children", BindingFlags.Instance | BindingFlags.NonPublic); + internal static MethodInfo miAddChild = typeof (GroupBase).GetMethod ("AddChild"); + internal static MethodInfo miGetChildren = typeof(GroupBase).GetProperty ("Children", BindingFlags.Instance | BindingFlags.Public).GetGetMethod(); internal static MethodInfo miLoadTmp = typeof (TemplatedControl).GetMethod ("loadTemplate", BindingFlags.Instance | BindingFlags.NonPublic); internal static PropertyInfo piContent = typeof(TemplatedContainer).GetProperty ("Content"); internal static MethodInfo miAddItem = typeof (TemplatedGroup).GetMethod ("AddItem", BindingFlags.Instance | BindingFlags.Public); @@ -504,8 +504,8 @@ namespace Crow.IML /// <param name="parentType">Parent type</param> /// <param name="index">Index of child, -1 for template root</param> internal static void emitGetChild(ILGenerator il, Type parentType, int index){ - if (typeof (Group).IsAssignableFrom (parentType)) { - il.Emit (OpCodes.Ldfld, fiChildren); + if (typeof (GroupBase).IsAssignableFrom (parentType)) { + il.Emit (OpCodes.Callvirt, miGetChildren); il.Emit(OpCodes.Ldc_I4, index); il.Emit (OpCodes.Callvirt, miGetGObjItem); return; diff --git a/Crow/src/IML/Node.cs b/Crow/src/IML/Node.cs index 811cfd6d..5ef078c1 100644 --- a/Crow/src/IML/Node.cs +++ b/Crow/src/IML/Node.cs @@ -39,7 +39,7 @@ namespace Crow.IML /// <returns>The child addition method</returns> /// <param name="childIdx">child index or, template root node has index == -1</param> public MethodInfo GetAddMethod(int childIdx){ - if (typeof (Group).IsAssignableFrom (CrowType)) + if (typeof (GroupBase).IsAssignableFrom (CrowType)) return CompilerServices.miAddChild; if (typeof (Container).IsAssignableFrom (CrowType)) return CompilerServices.miSetChild; diff --git a/Crow/src/ItemTemplate.cs b/Crow/src/ItemTemplate.cs index e4fc2d8e..7e2f7194 100644 --- a/Crow/src/ItemTemplate.cs +++ b/Crow/src/ItemTemplate.cs @@ -279,8 +279,8 @@ namespace Crow } public static List<Widget> GetChildren (this Widget go) { Type goType = go.GetType (); - if (typeof (Group).IsAssignableFrom (goType)) - return (go as Group).Children; + if (typeof (GroupBase).IsAssignableFrom (goType)) + return (go as GroupBase).Children; if (typeof (Container).IsAssignableFrom (goType)) return new List<Widget> (new Widget[] { (go as Container).Child }); if (typeof (TemplatedContainer).IsAssignableFrom (goType)) diff --git a/Crow/src/Widgets/Group.cs b/Crow/src/Widgets/Group.cs index d5e3d5e0..4ce70c4a 100644 --- a/Crow/src/Widgets/Group.cs +++ b/Crow/src/Widgets/Group.cs @@ -12,76 +12,20 @@ using static Crow.Logger; namespace Crow { - public class Group : Widget + public class Group : GroupBase { - #if DESIGN_MODE - public override bool FindByDesignID(string designID, out Widget go){ - go = null; - if (base.FindByDesignID (designID, out go)) - return true; - childrenRWLock.EnterReadLock (); - foreach (Widget w in Children) { - if (!w.FindByDesignID (designID, out go)) - continue; - childrenRWLock.ExitReadLock (); - return true; - } - childrenRWLock.ExitReadLock (); - return false; - } - public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem) - { - if (this.design_isTGItem) - return; - base.getIML (doc, parentElem); - foreach (Widget g in Children) { - g.getIML (doc, parentElem.LastChild); - } - } - #endif - - protected ReaderWriterLockSlim childrenRWLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); #region CTOR public Group () {} public Group(Interface iface, string style = null) : base (iface, style) { } #endregion + internal Widget largestChild = null; + internal Widget tallestChild = null; #region EVENT HANDLERS public event EventHandler<EventArgs> ChildrenCleared; #endregion - - internal Widget largestChild = null; - internal Widget tallestChild = null; - - bool _multiSelect = false; - ObservableList<Widget> children = new ObservableList<Widget>(); - - public virtual ObservableList<Widget> Children => children; - [DefaultValue(false)] - public bool MultiSelect - { - get => _multiSelect; - set { _multiSelect = value; } - } - public virtual void AddChild(Widget g){ - if (disposed) { - DbgLogger.AddEvent (DbgEvtType.AlreadyDisposed | DbgEvtType.GOAddChild); - return; - } - - childrenRWLock.EnterWriteLock(); - - g.Parent = this; - Children.Add (g); - - childrenRWLock.ExitWriteLock(); - - //g.RegisteredLayoutings = LayoutingType.None; - g.LayoutChanged += OnChildLayoutChanges; - g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); - } - public virtual void RemoveChild(Widget child) + public override void RemoveChild(Widget child) { child.LayoutChanged -= OnChildLayoutChanges; //check if HoverWidget is removed from Tree @@ -106,12 +50,7 @@ namespace Crow this.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); } - public virtual void DeleteChild(Widget child) - { - RemoveChild (child); - child.Dispose (); - } - public virtual void InsertChild (int idx, Widget g) { + public override void InsertChild (int idx, Widget g) { if (disposed) { DbgLogger.AddEvent (DbgEvtType.AlreadyDisposed | DbgEvtType.GOAddChild); return; @@ -120,20 +59,23 @@ namespace Crow g.Parent = this; Children.Insert (idx, g); - + childrenRWLock.ExitWriteLock (); - g.RegisteredLayoutings = LayoutingType.None; + if (g.LastSlots.Width > contentSize.Width) { + largestChild = g; + contentSize.Width = g.LastSlots.Width; + } + if (g.LastSlots.Height > contentSize.Height) { + tallestChild = g; + contentSize.Height = g.LastSlots.Height; + } + + g.LayoutChanged += OnChildLayoutChanges; g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); } - public virtual void RemoveChild (int idx) { - RemoveChild (children[idx]); - } - public virtual void DeleteChild (int idx) { - DeleteChild (children[idx]); - } - public virtual void ClearChildren() + public override void ClearChildren() { childrenRWLock.EnterWriteLock (); @@ -151,104 +93,17 @@ namespace Crow RegisterForLayouting (LayoutingType.Sizing); ChildrenCleared.Raise (this, new EventArgs ()); } - public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) - { - base.OnDataSourceChanged (this, e); - - childrenRWLock.EnterReadLock (); - foreach (Widget g in Children) { - if (g.localDataSourceIsNull & g.localLogicalParentIsNull) - g.OnDataSourceChanged (g, e); - } - childrenRWLock.ExitReadLock (); - } - - public void putWidgetOnTop(Widget w) - { - if (Children.Contains(w)) - { - childrenRWLock.EnterWriteLock (); - - Children.Remove (w); - Children.Add (w); - - childrenRWLock.ExitWriteLock (); - } - } - public void putWidgetOnBottom(Widget w) - { - if (Children.Contains(w)) - { - childrenRWLock.EnterWriteLock (); - - Children.Remove (w); - Children.Insert (0, w); - - childrenRWLock.ExitWriteLock (); - } - } #region GraphicObject overrides - - public override Widget FindByName (string nameToFind) - { - if (Name == nameToFind) - return this; - Widget tmp = null; - - childrenRWLock.EnterReadLock (); - - foreach (Widget w in Children) { - tmp = w.FindByName (nameToFind); - if (tmp != null) - break; - } - - childrenRWLock.ExitReadLock (); - - return tmp; - } - public override Widget FindByType<T> () - { - if (this is T) - return this; - Widget tmp = null; - - childrenRWLock.EnterReadLock (); - - foreach (Widget w in Children) { - tmp = w.FindByType<T> (); - if (tmp != null) - break; - } - - childrenRWLock.ExitReadLock (); - - return tmp; - } - public override bool Contains (Widget goToFind) - { - foreach (Widget w in Children) { - if (w == goToFind) - return true; - if (w.Contains (goToFind)) - return true; - } - return false; - } public override int measureRawSize (LayoutingType lt) { if (Children.Count > 0) { if (lt == LayoutingType.Width) { if (largestChild == null) - searchLargestChild (); - if (largestChild == null) - searchLargestChild (true); + searchLargestChild (); } else { if (tallestChild == null) - searchTallestChild (); - if (tallestChild == null) - searchTallestChild (true); + searchTallestChild (); } } return base.measureRawSize (lt); @@ -262,97 +117,29 @@ namespace Crow //position smaller objects in group when group size is fit switch (layoutType) { case LayoutingType.Width: + //childrenRWLock.EnterReadLock (); foreach (Widget c in Children) { if (c.Width.IsRelativeToParent) c.RegisterForLayouting (LayoutingType.Width); else c.RegisterForLayouting (LayoutingType.X); } + //childrenRWLock.ExitReadLock (); break; case LayoutingType.Height: + //childrenRWLock.EnterReadLock (); foreach (Widget c in Children) { if (c.Height.IsRelativeToParent) c.RegisterForLayouting (LayoutingType.Height); else c.RegisterForLayouting (LayoutingType.Y); } + //childrenRWLock.ExitReadLock (); break; } childrenRWLock.ExitReadLock (); } - protected override void onDraw (Context gr) - { - DbgLogger.StartEvent (DbgEvtType.GODraw, this); - - base.onDraw (gr); - - if (ClipToClientRect) { - gr.Save (); - //clip to client zone - CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); - gr.Clip (); - } - - childrenRWLock.EnterReadLock (); - - for (int i = 0; i < Children.Count; i++) - Children[i].Paint (gr); - - childrenRWLock.ExitReadLock (); - - if (ClipToClientRect) - gr.Restore (); - - DbgLogger.EndEvent (DbgEvtType.GODraw); - } - protected override void UpdateCache (Context ctx) - { - DbgLogger.StartEvent(DbgEvtType.GOUpdateCache, this); - if (!Clipping.IsEmpty) { - using (Context gr = new Context (bmp)) { - for (int i = 0; i < Clipping.NumRectangles; i++) - gr.Rectangle(Clipping.GetRectangle(i)); - gr.ClipPreserve(); - gr.Operator = Operator.Clear; - gr.Fill(); - gr.Operator = Operator.Over; - - base.onDraw (gr); - - if (ClipToClientRect) { - CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); - gr.Clip (); - } - - childrenRWLock.EnterReadLock (); - - foreach (Widget c in Children) { - if (!c.IsVisible) - continue; - if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out) - continue; - c.Paint (gr); - } - - childrenRWLock.ExitReadLock (); - - #if DEBUG_CLIP_RECTANGLE - /*gr.LineWidth = 1; - gr.SetSourceColor(Color.DarkMagenta.AdjustAlpha (0.8)); - for (int i = 0; i < Clipping.NumRectangles; i++) - gr.Rectangle(Clipping.GetRectangle(i)); - gr.Stroke ();*/ - #endif - } - DbgLogger.AddEvent (DbgEvtType.GOResetClip, this); - Clipping.Reset (); - }/*else - Console.WriteLine("GROUP REPAINT WITH EMPTY CLIPPING");*/ - paintCache (ctx, Slot + Parent.ClientRectangle.Position); - DbgLogger.EndEvent(DbgEvtType.GOUpdateCache); - } #endregion - public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { DbgLogger.StartEvent(DbgEvtType.GOOnChildLayoutChange, this); @@ -361,38 +148,28 @@ namespace Crow switch (arg.LayoutType) { case LayoutingType.Width: - if (Width != Measure.Fit) { - DbgLogger.EndEvent(DbgEvtType.GOOnChildLayoutChange); - return; - } - if (g.Slot.Width > contentSize.Width) { - largestChild = g; - contentSize.Width = g.Slot.Width; - } else if (g == largestChild) - searchLargestChild (); - else { - DbgLogger.EndEvent(DbgEvtType.GOOnChildLayoutChange); - return; + if (Width == Measure.Fit) { + if (g.Slot.Width > contentSize.Width) { + largestChild = g; + contentSize.Width = g.Slot.Width; + } else if (g == largestChild) + searchLargestChild (); + else + break; + this.RegisterForLayouting (LayoutingType.Width); } - - this.RegisterForLayouting (LayoutingType.Width); break; case LayoutingType.Height: - if (Height != Measure.Fit) { - DbgLogger.EndEvent(DbgEvtType.GOOnChildLayoutChange); - return; - } - if (g.Slot.Height > contentSize.Height) { - tallestChild = g; - contentSize.Height = g.Slot.Height; - } else if (g == tallestChild) - searchTallestChild (); - else { - DbgLogger.EndEvent(DbgEvtType.GOOnChildLayoutChange); - return; + if (Height == Measure.Fit) { + if (g.Slot.Height > contentSize.Height) { + tallestChild = g; + contentSize.Height = g.Slot.Height; + } else if (g == tallestChild) + searchTallestChild (); + else + break; + this.RegisterForLayouting (LayoutingType.Height); } - - this.RegisterForLayouting (LayoutingType.Height); break; } DbgLogger.EndEvent(DbgEvtType.GOOnChildLayoutChange); @@ -403,10 +180,12 @@ namespace Crow tallestChild = null; contentSize = 0; } - void searchLargestChild (bool forceMeasure = false) + protected virtual void searchLargestChild (bool forceMeasure = false) { DbgLogger.StartEvent (DbgEvtType.GOSearchLargestChild, this); + //childrenRWLock.EnterReadLock (); + largestChild = null; contentSize.Width = 0; for (int i = 0; i < Children.Count; i++) { @@ -414,8 +193,8 @@ namespace Crow continue; int cw = 0; if (forceMeasure) - cw = children [i].measureRawSize (LayoutingType.Width); - else if (children [i].RegisteredLayoutings.HasFlag (LayoutingType.Width)) + cw = Children [i].measureRawSize (LayoutingType.Width); + else if (Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Width)) continue; else cw = Children [i].Slot.Width; @@ -424,13 +203,19 @@ namespace Crow largestChild = Children [i]; } } + if (largestChild == null && !forceMeasure) + searchLargestChild (true); + + //childrenRWLock.ExitReadLock (); DbgLogger.EndEvent (DbgEvtType.GOSearchLargestChild); } - void searchTallestChild (bool forceMeasure = false) + protected virtual void searchTallestChild (bool forceMeasure = false) { DbgLogger.StartEvent (DbgEvtType.GOSearchTallestChild, this); + //childrenRWLock.EnterReadLock (); + tallestChild = null; contentSize.Height = 0; for (int i = 0; i < Children.Count; i++) { @@ -438,8 +223,8 @@ namespace Crow continue; int ch = 0; if (forceMeasure) - ch = children [i].measureRawSize (LayoutingType.Height); - else if (children [i].RegisteredLayoutings.HasFlag (LayoutingType.Height)) + ch = Children [i].measureRawSize (LayoutingType.Height); + else if (Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Height)) continue; else ch = Children [i].Slot.Height; @@ -448,50 +233,12 @@ namespace Crow tallestChild = Children [i]; } } + if (tallestChild == null && !forceMeasure) + searchTallestChild (true); - DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild); - } - + //childrenRWLock.ExitReadLock (); - #region Mouse handling - public override void checkHoverWidget (MouseMoveEventArgs e) { - base.checkHoverWidget (e);//TODO:check if not possible to put it at beginning of meth to avoid doubled check to DropTarget. - childrenRWLock.EnterReadLock (); - for (int i = Children.Count - 1; i >= 0; i--) { - if (Children[i].MouseIsIn (e.Position)) { - Children[i].checkHoverWidget (e); - childrenRWLock.ExitReadLock (); - return; - } - } - childrenRWLock.ExitReadLock (); - } -// public override bool PointIsIn (ref Point m) -// { -// if (!base.PointIsIn (ref m)) -// return false; -// if (CurrentInterface.HoverWidget == this) -// return true; -// lock (Children) { -// for (int i = Children.Count - 1; i >= 0; i--) { -// if (Children [i].Slot.ContainsOrIsEqual (m) && !(bool)CurrentInterface.HoverWidget?.IsOrIsInside(Children[i])) { -// return false; -// } -// } -// } -// return true; -// } - #endregion - - protected override void Dispose (bool disposing) - { - if (disposing) { - childrenRWLock.EnterReadLock (); - foreach (Widget c in children) - c.Dispose (); - childrenRWLock.ExitReadLock (); - } - base.Dispose (disposing); + DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild); } } } diff --git a/Crow/src/Widgets/GroupBase.cs b/Crow/src/Widgets/GroupBase.cs new file mode 100644 index 00000000..0ef24bda --- /dev/null +++ b/Crow/src/Widgets/GroupBase.cs @@ -0,0 +1,302 @@ +// 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; +using System.ComponentModel; +using Crow.Cairo; +using System.Threading; + +using static Crow.Logger; + +namespace Crow +{ + public abstract class GroupBase : Widget + { + #if DESIGN_MODE + public override bool FindByDesignID(string designID, out Widget go){ + go = null; + if (base.FindByDesignID (designID, out go)) + return true; + childrenRWLock.EnterReadLock (); + foreach (Widget w in Children) { + if (!w.FindByDesignID (designID, out go)) + continue; + childrenRWLock.ExitReadLock (); + return true; + } + childrenRWLock.ExitReadLock (); + return false; + } + public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem) + { + if (this.design_isTGItem) + return; + base.getIML (doc, parentElem); + foreach (Widget g in Children) { + g.getIML (doc, parentElem.LastChild); + } + } + #endif + protected ReaderWriterLockSlim childrenRWLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + + #region CTOR + public GroupBase () {} + public GroupBase (Interface iface, string style = null) : base (iface, style) { } + #endregion + + bool _multiSelect = false; + ObservableList<Widget> children = new ObservableList<Widget>(); + public virtual ObservableList<Widget> Children => children; + + [DefaultValue(false)] + public bool MultiSelect + { + get => _multiSelect; + set { + if (_multiSelect == value) + return; + _multiSelect = value; + NotifyValueChangedAuto (_multiSelect); + } + } + public virtual void AddChild(Widget g){ + InsertChild (children.Count, g); + } + public virtual void RemoveChild(Widget child) + { + //check if HoverWidget is removed from Tree + if (IFace.HoverWidget != null) { + if (this.Contains (IFace.HoverWidget)) + IFace.HoverWidget = null; + } + + childrenRWLock.EnterWriteLock (); + + Children.Remove(child); + child.Parent = null; + child.LogicalParent = null; + + childrenRWLock.ExitWriteLock (); + } + public virtual void DeleteChild(Widget child) + { + RemoveChild (child); + child.Dispose (); + } + public virtual void InsertChild (int idx, Widget g) { + if (disposed) { + DbgLogger.AddEvent (DbgEvtType.AlreadyDisposed | DbgEvtType.GOAddChild); + return; + } + childrenRWLock.EnterWriteLock (); + + g.Parent = this; + Children.Insert (idx, g); + + childrenRWLock.ExitWriteLock (); + } + public virtual void RemoveChild (int idx) { + RemoveChild (children[idx]); + } + public virtual void DeleteChild (int idx) { + DeleteChild (children[idx]); + } + public virtual void ClearChildren() + { + childrenRWLock.EnterWriteLock (); + + while (Children.Count > 0) { + Widget g = Children [Children.Count - 1]; + Children.RemoveAt (Children.Count - 1); + g.Dispose (); + } + + childrenRWLock.ExitWriteLock (); + } + public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) + { + base.OnDataSourceChanged (this, e); + + childrenRWLock.EnterReadLock (); + foreach (Widget g in Children) { + if (g.localDataSourceIsNull & g.localLogicalParentIsNull) + g.OnDataSourceChanged (g, e); + } + childrenRWLock.ExitReadLock (); + } + + public void putWidgetOnTop(Widget w) + { + if (Children.Contains(w)) + { + childrenRWLock.EnterWriteLock (); + + Children.Remove (w); + Children.Add (w); + + childrenRWLock.ExitWriteLock (); + } + } + public void putWidgetOnBottom(Widget w) + { + if (Children.Contains(w)) + { + childrenRWLock.EnterWriteLock (); + + Children.Remove (w); + Children.Insert (0, w); + + childrenRWLock.ExitWriteLock (); + } + } + + #region GraphicObject overrides + public override Widget FindByName (string nameToFind) + { + if (Name == nameToFind) + return this; + Widget tmp = null; + + childrenRWLock.EnterReadLock (); + + foreach (Widget w in Children) { + tmp = w.FindByName (nameToFind); + if (tmp != null) + break; + } + + childrenRWLock.ExitReadLock (); + + return tmp; + } + public override Widget FindByType<T> () + { + if (this is T) + return this; + Widget tmp = null; + + childrenRWLock.EnterReadLock (); + + foreach (Widget w in Children) { + tmp = w.FindByType<T> (); + if (tmp != null) + break; + } + + childrenRWLock.ExitReadLock (); + + return tmp; + } + public override bool Contains (Widget goToFind) + { + foreach (Widget w in Children) { + if (w == goToFind) + return true; + if (w.Contains (goToFind)) + return true; + } + return false; + } + + protected override void onDraw (Context gr) + { + DbgLogger.StartEvent (DbgEvtType.GODraw, this); + + base.onDraw (gr); + + if (ClipToClientRect) { + gr.Save (); + //clip to client zone + CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); + gr.Clip (); + } + + childrenRWLock.EnterReadLock (); + + for (int i = 0; i < Children.Count; i++) + Children[i].Paint (gr); + + childrenRWLock.ExitReadLock (); + + if (ClipToClientRect) + gr.Restore (); + + DbgLogger.EndEvent (DbgEvtType.GODraw); + } + protected override void UpdateCache (Context ctx) + { + DbgLogger.StartEvent(DbgEvtType.GOUpdateCache, this); + if (!Clipping.IsEmpty) { + using (Context gr = new Context (bmp)) { + for (int i = 0; i < Clipping.NumRectangles; i++) + gr.Rectangle(Clipping.GetRectangle(i)); + gr.ClipPreserve(); + gr.Operator = Operator.Clear; + gr.Fill(); + gr.Operator = Operator.Over; + + base.onDraw (gr); + + if (ClipToClientRect) { + CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); + gr.Clip (); + } + + childrenRWLock.EnterReadLock (); + + foreach (Widget c in Children) { + if (!c.IsVisible) + continue; + if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out) + continue; + c.Paint (gr); + } + + childrenRWLock.ExitReadLock (); + + #if DEBUG_CLIP_RECTANGLE + /*gr.LineWidth = 1; + gr.SetSourceColor(Color.DarkMagenta.AdjustAlpha (0.8)); + for (int i = 0; i < Clipping.NumRectangles; i++) + gr.Rectangle(Clipping.GetRectangle(i)); + gr.Stroke ();*/ + #endif + } + DbgLogger.AddEvent (DbgEvtType.GOResetClip, this); + Clipping.Reset (); + }/*else + Console.WriteLine("GROUP REPAINT WITH EMPTY CLIPPING");*/ + paintCache (ctx, Slot + Parent.ClientRectangle.Position); + DbgLogger.EndEvent(DbgEvtType.GOUpdateCache); + } + #endregion + + #region Mouse handling + public override void checkHoverWidget (MouseMoveEventArgs e) { + base.checkHoverWidget (e);//TODO:check if not possible to put it at beginning of meth to avoid doubled check to DropTarget. + childrenRWLock.EnterReadLock (); + for (int i = Children.Count - 1; i >= 0; i--) { + if (Children[i].MouseIsIn (e.Position)) { + Children[i].checkHoverWidget (e); + childrenRWLock.ExitReadLock (); + return; + } + } + childrenRWLock.ExitReadLock (); + } + #endregion + + protected override void Dispose (bool disposing) + { + if (disposing) { + childrenRWLock.EnterReadLock (); + foreach (Widget c in Children) + c.Dispose (); + childrenRWLock.ExitReadLock (); + } + base.Dispose (disposing); + } + } +} diff --git a/Crow/src/Widgets/Table copy.cs b/Crow/src/Widgets/Table copy.cs new file mode 100644 index 00000000..5aeaede8 --- /dev/null +++ b/Crow/src/Widgets/Table copy.cs @@ -0,0 +1,259 @@ +// Copyright (c) 2019-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.ComponentModel; +using System.Linq; +using Crow.Cairo; + +namespace Crow +{ + /// <summary> + /// Table column definition + /// </summary> + public class Column2 : IValueChange + { + #region IValueChange implementation + public event EventHandler<ValueChangeEventArgs> ValueChanged; + public virtual void NotifyValueChanged (string MemberName, object _value) + => ValueChanged.Raise (this, new ValueChangeEventArgs (MemberName, _value)); + #endregion + + string caption; + Measure width = Measure.Fit; + public int ComputedWidth; + public Widget LargestWidget; + + public string Caption { + get => caption; + set { + if (caption == value) + return; + caption = value; + NotifyValueChanged ("Caption", caption); + } + } + /// <summary> + /// column width, special value 'Inherit' will be used to share table width equaly among columns + /// </summary> + /// <value>The column's width.</value> + public Measure Width { + get => width; + set { + if (width == value) + return; + width = value; + NotifyValueChanged ("Width", width); + } + } + + public static Column Parse (string str) { + if (string.IsNullOrEmpty (str)) + return null; + Column c = new Column(); + string[] tmp = str.Split (','); + c.Caption = tmp[0]; + if (tmp.Length > 1) + c.Width = Measure.Parse (tmp[1]); + return c; + } + } + + + public class Table2 : VerticalStack + { + #region CTOR + public Table2 () {} + public Table2 (Interface iface, string style = null) : base (iface, style) { } + #endregion + + //int lineWidth; + ObservableList<Column> columns = new ObservableList<Column>(); + + public ObservableList<Column> Columns { + get => columns; + set { + if (columns == value) + return; + if (columns != null) { + columns.ListAdd -= Ol_AddColumn; + columns.ListAdd -= Ol_RemoveColumn; + + foreach (Column c in columns) + c.ValueChanged += column_valueChanged; + } + + columns = value; + + if (columns != null) { + columns.ListAdd += Ol_AddColumn; + columns.ListAdd += Ol_RemoveColumn; + + foreach (Column c in columns) + c.ValueChanged += column_valueChanged; + + foreach (TableRow row in Children) { + for (int i = 0; i < columns.Count && i < row.Children.Count; i++) + row.Children[i].Width = columns[i].Width; + } + } + NotifyValueChangedAuto(columns); + } + } + + void column_valueChanged (object sender, ValueChangeEventArgs e) { + switch (e.MemberName) { + case "Width": + int columnIdx = columns.IndexOf (sender as Column); + foreach (TableRow row in Children.OfType<TableRow>().Where (r => r.Children.Count > columnIdx)) + row.Children[columnIdx].Width = (Measure)e.NewValue; + break; + } + } + + public override void AddChild (Widget child) { + if (!(child is TableRow tr)) + throw new Exception ("Table widget accept only TableRow as child."); + base.AddChild (child); + + tr.Children.ListAdd += Ol_tableRow_ChildAdd; + tr.Children.ListRemove += Ol_tableRow_ChildRemove; + tr.Children.ListClear += Ol_tableRow_ChildClear; + + for (int i = 0; i < columns.Count && i < tr.Children.Count; i++) + tr.Children[i].Width = columns[i].Width; + } + public override void RemoveChild(Widget child) + { + base.RemoveChild(child); + + TableRow tr = child as TableRow; + tr.Children.ListAdd -= Ol_tableRow_ChildAdd; + tr.Children.ListRemove -= Ol_tableRow_ChildRemove; + tr.Children.ListClear -= Ol_tableRow_ChildClear; + } + void Ol_tableRow_ChildAdd (object sender, ListChangedEventArg e) + { + Widget w = e.Element as Widget; + if (e.Index < Columns.Count) + w.Width = Columns[e.Index].Width; + w.LayoutChanged += onTableRow_ChildLayoutChanges; + } + void Ol_tableRow_ChildRemove (object sender, ListChangedEventArg e) { + Widget w = e.Element as Widget; + w.LayoutChanged -= onTableRow_ChildLayoutChanges; + } + void Ol_tableRow_ChildClear (object sender, ListClearEventArg e) { + foreach (Widget w in e.Elements) + w.LayoutChanged -= onTableRow_ChildLayoutChanges; + } + void onTableRow_ChildLayoutChanges (object sender, LayoutingEventArgs arg) { + if (Columns == null) + return; + Widget g = sender as Widget; + TableRow tr = g.Parent as TableRow; + int cIdx = tr.Children.IndexOf (g); + //if (cIdx < Columns.Count && Columns.wi) + } + void Ol_AddColumn (object sender, ListChangedEventArg e) { + (e.Element as Column).ValueChanged += column_valueChanged; + foreach (TableRow row in Children) { + for (int i = e.Index; i < columns.Count && i < row.Children.Count; i++) + row.Children[i].Width = columns[i].Width; + } + + } + void Ol_RemoveColumn (object sender, ListChangedEventArg e) { + (e.Element as Column).ValueChanged -= column_valueChanged; + foreach (TableRow row in Children) { + for (int i = e.Index; i < columns.Count && i < row.Children.Count; i++) + row.Children[i].Width = columns[i].Width; + } + } + + + public override void ChildrenLayoutingConstraints(ILayoutable layoutable, ref LayoutingType layoutType) + { + //trigger layouting for width only in the first row, the other will be set at the same horizontal position and width. + if (layoutable == Children[0]) + layoutType &= (~LayoutingType.X); + else + layoutType &= (~(LayoutingType.X|LayoutingType.Width)); + } + + //overriden to prevent search for largest child, all the rows have the same total width. + public override void ComputeChildrenPositions () { + int d = 0; + childrenRWLock.EnterReadLock(); + foreach (TableRow c in Children) { + if (!c.IsVisible) + continue; + c.Slot.Y = d; + d += c.Slot.Height + Spacing; + } + childrenRWLock.ExitReadLock(); + IsDirty = true; + } +/* public override bool UpdateLayout(LayoutingType layoutType) + { + RegisteredLayoutings &= (~layoutType); + + if (layoutType == LayoutingType.Width) { + //propagate column.width to each row's children + } + return base.UpdateLayout(layoutType); + }*/ + + /*public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { + TableRow row = sender as TableRow; + TableRow firstRow = Children[0] as TableRow; + + if (arg.LayoutType == LayoutingType.Width) { + if (row == firstRow) { + base.OnChildLayoutChanges (sender, arg); + foreach (TableRow r in Children.Skip(1)) { + r.contentSize = firstRow.contentSize; + setChildWidth (r, firstRow.Slot.Width); + } + } + } + + base.OnChildLayoutChanges (sender, arg); + }*/ + /*protected override void onDraw (Context gr) { + DbgLogger.StartEvent (DbgEvtType.GODraw, this); + + base.onDraw (gr); + + if (Children.Count > 0) { + + Rectangle cb = ClientRectangle; + TableRow fr = Children[0] as TableRow; + + + gr.LineWidth = lineWidth; + Foreground.SetAsSource (IFace, gr, cb); + CairoHelpers.CairoRectangle (gr, cb, CornerRadius, lineWidth); + double x = 0.5 + cb.Left + fr.Margin + 0.5 * fr.Spacing + fr.Children[0].Slot.Width; + for (int i = 1; i < fr.Children.Count ; i++) + { + gr.MoveTo (x, cb.Y); + gr.LineTo (x, cb.Bottom); + x += fr.Spacing + fr.Children[i].Slot.Width ; + } + + //horizontal lines + x = 0.5 + cb.Top + 0.5 * Spacing + Children[0].Slot.Height; + for (int i = 0; i < Children.Count - 1; i++) + { + gr.MoveTo (cb.Left, x); + gr.LineTo (cb.Right, x); + x += Spacing + Children[i].Slot.Height ; + } + gr.Stroke (); + } + + DbgLogger.EndEvent (DbgEvtType.GODraw); + }*/ + } +} diff --git a/Crow/src/Widgets/Table.cs b/Crow/src/Widgets/Table.cs index 0beafb56..5ddd1af8 100644 --- a/Crow/src/Widgets/Table.cs +++ b/Crow/src/Widgets/Table.cs @@ -22,7 +22,7 @@ namespace Crow string caption; Measure width = Measure.Fit; public int ComputedWidth; - public Widget LargestWidget; + public Widget LargestChild; public string Caption { get => caption; @@ -66,111 +66,306 @@ namespace Crow public Table () {} public Table (Interface iface, string style = null) : base (iface, style) { } #endregion + int columnSpacing, borderLineWidth, verticalLineWidth, horizontalLineWidth, rowsMargin; + ObservableList<Column> columns; + HorizontalStack HeaderRow; + string headerCellTemplate; + IML.Instantiator headerCellITor; - //int lineWidth; - ObservableList<Column> columns = new ObservableList<Column>(); + [DefaultValue ("#Crow.DefaultTableHeaderCell.template")] + public string HeaderCellTemplate { + get => headerCellTemplate; + set { + if (headerCellTemplate == value) + return; + headerCellTemplate = value; + NotifyValueChangedAuto (headerCellTemplate); + headerCellITor = new IML.Instantiator (IFace, HeaderCellTemplate); + createHeaderRow(); + } + } + public override void InsertChild (int idx, Widget g) { + g.Width = Measure.Stretched; + g.Margin = RowsMargin; + base.InsertChild (idx, g); + } + [DefaultValue (2)] + public int ColumnSpacing { + get => columnSpacing; + set { + if (columnSpacing == value) + return; + columnSpacing = value; + NotifyValueChangedAuto (columnSpacing); + if (HeaderRow != null) + HeaderRow.Spacing = ColumnSpacing; + //RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); + } + } + [DefaultValue (1)] + public int BorderLineWidth { + get => borderLineWidth; + set { + if (borderLineWidth == value) + return; + borderLineWidth = value; + NotifyValueChangedAuto (borderLineWidth); + RegisterForRedraw (); + } + } + [DefaultValue (1)] + public int HorizontalLineWidth { + get => horizontalLineWidth; + set { + if (horizontalLineWidth == value) + return; + horizontalLineWidth = value; + NotifyValueChangedAuto (horizontalLineWidth); + RegisterForRedraw (); + } + } + [DefaultValue (1)] + public int VerticalLineWidth { + get => verticalLineWidth; + set { + if (verticalLineWidth == value) + return; + verticalLineWidth = value; + NotifyValueChangedAuto (verticalLineWidth); + RegisterForRedraw (); + } + } + [DefaultValue (1)] + public int RowsMargin { + get => rowsMargin; + set { + if (rowsMargin == value) + return; + rowsMargin = value; + NotifyValueChangedAuto (rowsMargin); + childrenRWLock.EnterReadLock (); + foreach (Widget row in Children) + row.Margin = rowsMargin; + childrenRWLock.ExitReadLock (); + } + } + //int lineWidth; public ObservableList<Column> Columns { get => columns; set { if (columns == value) return; + if (columns != null) { + deleteHeaderRow (); + columns.ListAdd -= Ol_AddColumn; + columns.ListAdd -= Ol_RemoveColumn; + } + columns = value; + + if (columns != null) { + createHeaderRow (); + columns.ListAdd += Ol_AddColumn; + columns.ListAdd += Ol_RemoveColumn; + } NotifyValueChangedAuto(columns); } } - public override void AddChild (Widget child) { - TableRow tr = child as TableRow; - if (tr == null) - throw new Exception ("Table widget accept only TableRow as child."); - base.AddChild (child); + void deleteHeaderRow () { + if (HeaderRow == null) + return; + DeleteChild (HeaderRow); + HeaderRow = null; } - /*public override void ChildrenLayoutingConstraints(ILayoutable layoutable, ref LayoutingType layoutType) - { - //trigger layouting for width only in the first row, the other will be set at the same horizontal position and width. - if (layoutable == Children[0]) - layoutType &= (~LayoutingType.X); - else - layoutType &= (~(LayoutingType.X|LayoutingType.Width)); - }*/ + void createHeaderRow () { + deleteHeaderRow (); + if (Columns == null || headerCellITor == null) + return; + HeaderRow = new HorizontalStack(IFace, "TableHeaderRow") {Spacing = ColumnSpacing}; + InsertChild (0, HeaderRow); + foreach (Column c in Columns) { + Widget cell = headerCellITor.CreateInstance(); + cell.LayoutChanged += onHeaderCell_LayoutChanges; + HeaderRow.AddChild (cell); + cell.DataSource = c; + } + } + + void Ol_AddColumn (object sender, ListChangedEventArg e) { + HeaderRow.InsertChild (e.Index, headerCellITor.CreateInstance()); + HeaderRow.DataSource = e.Element; + } + void Ol_RemoveColumn (object sender, ListChangedEventArg e) { + Widget w = HeaderRow.Children[e.Index]; + HeaderRow.RemoveChild (e.Index); + w.Dispose (); + } + void onHeaderCell_LayoutChanges (object sender, LayoutingEventArgs e) { + if (Columns == null) + return; + if (e.LayoutType == LayoutingType.Width) { + Widget g = sender as Widget; + int cIdx = HeaderRow.Children.IndexOf (g); + if (cIdx < Columns.Count && Columns[cIdx].Width.IsFit) + searchLargestChildInColumn (cIdx); + childrenRWLock.EnterReadLock (); + for (int i = 1; i < Children.Count; i++) { + TableRow row = Children[i] as TableRow; + if (row.Children.Count <= cIdx) + continue; + setRowCellWidth (row.Children[cIdx], g.Slot.Width); + } + childrenRWLock.ExitReadLock (); - //overriden to prevent search for largest child, all the rows as the same total width. - public override void ComputeChildrenPositions () { - int d = 0; - childrenRWLock.EnterReadLock(); - foreach (Widget c in Children) { - if (!c.Visible) - continue; - c.Slot.Y = d; - d += c.Slot.Height + Spacing; + RegisterForRedraw (); + } else if (e.LayoutType == LayoutingType.X) { + Widget g = sender as Widget; + int cIdx = HeaderRow.Children.IndexOf (g); + childrenRWLock.EnterReadLock (); + for (int i = 1; i < Children.Count; i++) { + TableRow row = Children[i] as TableRow; + if (row.Children.Count <= cIdx) + continue; + row.Children[cIdx].Slot.X = g.Slot.X; + row.RegisterForRedraw(); + } + childrenRWLock.ExitReadLock (); + RegisterForRedraw (); } - childrenRWLock.ExitReadLock(); - IsDirty = true; } - public override bool UpdateLayout(LayoutingType layoutType) + protected void setRowCellWidth (Widget w, int newW) { + if (newW == w.Slot.Width) + return; + + w.Slot.Width = newW; + w.IsDirty = true; + w.OnLayoutChanges (LayoutingType.Width); + w.LastSlots.Width = w.Slot.Width; + w.RegisterForRedraw (); + } + + public override void ClearChildren() { - RegisteredLayoutings &= (~layoutType); + base.ClearChildren(); + createHeaderRow (); + } + + void searchLargestChildInColumn (int cIdx) + { + DbgLogger.StartEvent (DbgEvtType.GOSearchLargestChild, this); + + Column c = Columns[cIdx]; + + childrenRWLock.EnterReadLock (); - if (layoutType == LayoutingType.Width) { - //propagate column.width to each row's children - foreach (TableRow row in Children) { - for (int i = 0; i < Columns.Count && i < row.Children.Count; i++) - row.Children[i].Width = Columns[i].Width; - } + c.LargestChild = null; + int largestWidth = 0; + for (int i = 1; i < Children.Count; i++) { + TableRow row = Children[i] as TableRow; + if (!row.IsVisible) + continue; + int cw = row.Children [cIdx]. measureRawSize (LayoutingType.Width); + if (cw > largestWidth) { + largestWidth = cw; + c.LargestChild = row.Children [cIdx]; + } } - return base.UpdateLayout(layoutType); - } - - /*public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { - TableRow row = sender as TableRow; - TableRow firstRow = Children[0] as TableRow; + childrenRWLock.ExitReadLock (); - if (arg.LayoutType == LayoutingType.Width) { - if (row == firstRow) { - base.OnChildLayoutChanges (sender, arg); - foreach (TableRow r in Children.Skip(1)) { - r.contentSize = firstRow.contentSize; - setChildWidth (r, firstRow.Slot.Width); - } + if (HeaderRow.Children[cIdx].Slot.Width > largestWidth) { + c.LargestChild = HeaderRow.Children[cIdx]; + return; + } + HeaderRow.Children[cIdx].Slot.Width = largestWidth; + //HeaderRow.adjustStretchedGo (LayoutingType.Width); + + DbgLogger.EndEvent (DbgEvtType.GOSearchLargestChild); + } + int splitIndex = -1; + const int minColumnSize = 10; + public override void onMouseMove(object sender, MouseMoveEventArgs e) + { + + if (ColumnSpacing > 0 && Columns.Count > 0) { + Point m = ScreenPointToLocal (e.Position); + if (IFace.IsDown (Glfw.MouseButton.Left) && splitIndex >= 0) { + int splitPos = (int)(0.5 * ColumnSpacing + m.X); + if (splitPos > HeaderRow.Children[splitIndex].Slot.Left + minColumnSize && splitPos < HeaderRow.Children[splitIndex+1].Slot.Right - minColumnSize) { + Columns[splitIndex+1].Width = HeaderRow.Children[splitIndex+1].Slot.Right - splitPos; + splitPos -= ColumnSpacing; + Columns[splitIndex].Width = splitPos - HeaderRow.Children[splitIndex].Slot.Left; + HeaderRow.RegisterForLayouting (LayoutingType.ArrangeChildren); + e.Handled = true; + } + //Console.WriteLine ($"left:{HeaderRow.Children[splitIndex].Slot.Left} right:{HeaderRow.Children[splitIndex+1].Slot.Right} splitPos:{splitPos} m:{m}"); + } else { + splitIndex = -1; + for (int i = 0; i < Columns.Count - 1; i++) + { + Rectangle r = HeaderRow.Children[i].Slot; + if (m.X >= r.Right) { + r = HeaderRow.Children[i+1].Slot; + if (m.X <= r.Left && Columns.Count - 1 > i ) { + IFace.MouseCursor = MouseCursor.sb_h_double_arrow; + splitIndex = i; + e.Handled = true; + break; + } + } + } + if (splitIndex < 0 && IFace.MouseCursor == MouseCursor.sb_h_double_arrow) + IFace.MouseCursor = MouseCursor.top_left_arrow; } } + base.onMouseMove(sender, e); + } - base.OnChildLayoutChanges (sender, arg); - }*/ - /*protected override void onDraw (Context gr) { + + protected override void onDraw (Context gr) { DbgLogger.StartEvent (DbgEvtType.GODraw, this); base.onDraw (gr); - if (Children.Count > 0) { + if (Columns != null && columns.Count > 0 && HeaderRow != null) { Rectangle cb = ClientRectangle; - TableRow fr = Children[0] as TableRow; - - - gr.LineWidth = lineWidth; - Foreground.SetAsSource (IFace, gr, cb); - CairoHelpers.CairoRectangle (gr, cb, CornerRadius, lineWidth); - double x = 0.5 + cb.Left + fr.Margin + 0.5 * fr.Spacing + fr.Children[0].Slot.Width; - for (int i = 1; i < fr.Children.Count ; i++) - { - gr.MoveTo (x, cb.Y); - gr.LineTo (x, cb.Bottom); - x += fr.Spacing + fr.Children[i].Slot.Width ; + + Foreground.SetAsSource (IFace, gr, cb); + if (BorderLineWidth > 0) { + gr.LineWidth = BorderLineWidth; + CairoHelpers.CairoRectangle (gr, cb, CornerRadius, borderLineWidth); + gr.Stroke (); + } + double x = 0; + if (VerticalLineWidth > 0) { + gr.LineWidth = VerticalLineWidth; + x = cb.Left + HeaderRow.Margin + 0.5 * ColumnSpacing + HeaderRow.Children[0].Slot.Width;// - 0.5 * VerticalLineWidth; + for (int i = 1; i < HeaderRow.Children.Count ; i++) + { + gr.MoveTo (x, cb.Y); + gr.LineTo (x, cb.Bottom); + x += columnSpacing + HeaderRow.Children[i].Slot.Width ; + } + gr.Stroke (); } - //horizontal lines - x = 0.5 + cb.Top + 0.5 * Spacing + Children[0].Slot.Height; - for (int i = 0; i < Children.Count - 1; i++) - { - gr.MoveTo (cb.Left, x); - gr.LineTo (cb.Right, x); - x += Spacing + Children[i].Slot.Height ; + if (HorizontalLineWidth > 0) { + gr.LineWidth = HorizontalLineWidth; + x = cb.Top + 0.5 * Spacing + Children[0].Slot.Height;// - 0.5 * HorizontalLineWidth; + for (int i = 1; i < Children.Count; i++) + { + gr.MoveTo (cb.Left, x); + gr.LineTo (cb.Right, x); + x += Spacing + Children[i].Slot.Height ; + } + gr.Stroke (); } - gr.Stroke (); + } DbgLogger.EndEvent (DbgEvtType.GODraw); - }*/ - } + } + + } } diff --git a/Crow/src/Widgets/TableRow copy.cs b/Crow/src/Widgets/TableRow copy.cs new file mode 100644 index 00000000..2184d486 --- /dev/null +++ b/Crow/src/Widgets/TableRow copy.cs @@ -0,0 +1,321 @@ +// Copyright (c) 2019-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.ComponentModel; +using System.Linq; +using Crow.Cairo; +using Glfw; + +namespace Crow +{ + public class TableRow2 : Group, ISelectable { + #region ISelectable implementation + bool isSelected; + public event EventHandler Selected; + public event EventHandler Unselected; + [DefaultValue (false)] + public virtual bool IsSelected { + get { return isSelected; } + set { + if (isSelected == value) + return; + isSelected = value; + + if (isSelected) + Selected.Raise (this, null); + else + Unselected.Raise (this, null); + + NotifyValueChangedAuto (isSelected); + } + } + #endregion + + public Table Table => Parent as Table; + + public override void ChildrenLayoutingConstraints(ILayoutable layoutable, ref LayoutingType layoutType) + { + //trigger layouting for width only in the first row, the other will be set at the same horizontal position and width. + if (Table == null) { + base.ChildrenLayoutingConstraints (layoutable, ref layoutType); + return; + } + if (this == Table.Children[0]) + layoutType &= (~LayoutingType.X); + else + layoutType &= (~(LayoutingType.X|LayoutingType.Width)); + } + + + public override void OnLayoutChanges(LayoutingType layoutType) + { + switch (layoutType) { + case LayoutingType.Width: + RegisterForLayouting (LayoutingType.X); + break; + case LayoutingType.Height: + childrenRWLock.EnterReadLock (); + foreach (Widget c in Children.Where (cc => cc.Height.IsRelativeToParent)) + c.RegisterForLayouting (LayoutingType.Height); + childrenRWLock.ExitReadLock (); + break; + } + raiseLayoutChanged (layoutType); + } + + //all the rows have equal size + protected override void searchLargestChild(bool forceMeasure = false) {} + + + + + /*public override void ComputeChildrenPositions () { + if (Children.Count == 0) + return; + int spacing = Table.Spacing; + ObservableList<Column> cols = Table.Columns; + + Widget first = Children[0]; + TableRow firstRow = Table.Children[0] as TableRow; + + if (firstRow == this) { + base.ComputeChildrenPositions(); + return; + } + childrenRWLock.EnterReadLock(); + + for (int i = 0; i < Children.Count && i < firstRow.Children.Count; i++) + { + Widget w = Children[i]; + + w.Slot.X = firstRow.Children[i].Slot.X; + setChildWidth (w, firstRow.Children[i].Slot.Width); + + } + + childrenRWLock.ExitReadLock(); + IsDirty = true; + }*/ + + + + + + /*public override void ComputeChildrenPositions () { + if (Children.Count == 0) + return; + int spacing = Table.Spacing; + ObservableList<Column> cols = Table.Columns; + + Widget first = Children[0]; + TableRow firstRow = Table.Children[0] as TableRow; + + if (firstRow == this) { + base.ComputeChildrenPositions(); + return; + } + childrenRWLock.EnterReadLock(); + + for (int i = 0; i < Children.Count && i < firstRow.Children.Count; i++) + { + Widget w = Children[i]; + + w.Slot.X = firstRow.Children[i].Slot.X; + setChildWidth (w, firstRow.Children[i].Slot.Width); + + } + + childrenRWLock.ExitReadLock(); + IsDirty = true; + }*/ + + + + + + /*public override void ComputeChildrenPositions () { + if (Children.Count == 0) + return; + int spacing = Table.Spacing; + ObservableList<Column> cols = Table.Columns; + + Widget first = Children[0]; + TableRow firstRow = Table.Children[0] as TableRow; + + if (firstRow == this) { + base.ComputeChildrenPositions(); + return; + } + childrenRWLock.EnterReadLock(); + + for (int i = 0; i < Children.Count && i < firstRow.Children.Count; i++) + { + Widget w = Children[i]; + + w.Slot.X = firstRow.Children[i].Slot.X; + setChildWidth (w, firstRow.Children[i].Slot.Width); + + } + + childrenRWLock.ExitReadLock(); + IsDirty = true; + }*/ + + + + + + /*public override void ComputeChildrenPositions () { + if (Children.Count == 0) + return; + int spacing = Table.Spacing; + ObservableList<Column> cols = Table.Columns; + + Widget first = Children[0]; + TableRow firstRow = Table.Children[0] as TableRow; + + if (firstRow == this) { + base.ComputeChildrenPositions(); + return; + } + childrenRWLock.EnterReadLock(); + + for (int i = 0; i < Children.Count && i < firstRow.Children.Count; i++) + { + Widget w = Children[i]; + + w.Slot.X = firstRow.Children[i].Slot.X; + setChildWidth (w, firstRow.Children[i].Slot.Width); + + } + + childrenRWLock.ExitReadLock(); + IsDirty = true; + }*/ + + /*public override bool UpdateLayout(LayoutingType layoutType) + { + RegisteredLayoutings &= (~layoutType); + + if (Table == null) + return false; + TableRow firstRow = Table.Children[0] as TableRow; + if (layoutType == LayoutingType.Width) { + if (firstRow.RegisteredLayoutings.HasFlag (LayoutingType.Width)) + return false; + if (this != firstRow) { + Slot.Width = firstRow.Slot.Width; + if (Slot.Width != LastSlots.Width) { + IsDirty = true; + OnLayoutChanges (layoutType); + LastSlots.Width = Slot.Width; + } + if (RegisteredLayoutings == LayoutingType.None && IsDirty) + IFace.EnqueueForRepaint (this); + + return true; + } + } + + return base.UpdateLayout(layoutType); + }*/ + /*public override int measureRawSize (LayoutingType lt) { + if (lt == LayoutingType.Width) { + if (Table == null) + return -1; + TableRow firstRow = Table.Children[0] as TableRow; + if (this != firstRow) { + if (firstRow.RegisteredLayoutings.HasFlag (LayoutingType.Width)) + return -1; + contentSize = firstRow.contentSize; + return firstRow.measureRawSize (lt); + } + + } + return base.measureRawSize (lt); + }*/ + /*public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { + if (arg.LayoutType == LayoutingType.Width) { + Widget w = sender as Widget; + TableRow firstRow = Table.Children[0] as TableRow; + int c = Children.IndexOf(w); + if (c < Table.Columns.Count) { + Column col = Table.Columns[c]; + if (col.Width.IsFit) { + if (col.LargestWidget == null || w.Slot.Width > col.ComputedWidth) { + col.ComputedWidth = w.Slot.Width; + col.LargestWidget = w; + } else if (w == col.LargestWidget) + Console.WriteLine ("must search for largest widget"); + }else if (w == firstRow) + col.ComputedWidth = w.Slot.Width; + + } + Console.WriteLine ($"ROW:{Table.Children.IndexOf(this)} COL:{c} {w.LastSlots.Width} -> {w.Slot.Width} "); + } + base.OnChildLayoutChanges (sender, arg); + }*/ + /*public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { + Widget go = sender as Widget; + TableRow row = go.Parent as TableRow; + TableRow firstRow = Table.Children[0] as TableRow; + + if (arg.LayoutType == LayoutingType.Width) { + if (row == firstRow) { + base.OnChildLayoutChanges (sender, arg); + int idx = Children.IndexOf (go); + foreach (TableRow r in Table.Children.Skip(1)) { + if (idx < r.Children.Count) + r.setChildWidth (r.Children[idx], go.Slot.Width); + r.contentSize = firstRow.contentSize; + } + } //else + this.RegisterForLayouting (LayoutingType.ArrangeChildren); + return; + } + + base.OnChildLayoutChanges (sender, arg); + }*/ + int splitIndex = -1; + const int minColumnSize = 10; + int Spacing => Table.Spacing; + public override void onMouseMove(object sender, MouseMoveEventArgs e) + { + if (Spacing > 0 && Table != null && Table.Children.Count > 0) { + Point m = ScreenPointToLocal (e.Position); + if (IFace.IsDown (Glfw.MouseButton.Left) && splitIndex >= 0) { + TableRow firstRow = Table.Children[0] as TableRow; + Rectangle cb = ClientRectangle; + int splitPos = (int)(0.5 * Spacing + m.X); + if (splitPos > firstRow.Children[splitIndex].Slot.Left + minColumnSize && splitPos < firstRow.Children[splitIndex+1].Slot.Right - minColumnSize) { + Table.Columns[splitIndex+1].Width = firstRow.Children[splitIndex+1].Slot.Right - splitPos; + splitPos -= Spacing; + Table.Columns[splitIndex].Width = splitPos - firstRow.Children[splitIndex].Slot.Left; + Table.RegisterForLayouting (LayoutingType.Width); + e.Handled = true; + } + //Console.WriteLine ($"left:{firstRow.Children[splitIndex].Slot.Left} right:{firstRow.Children[splitIndex+1].Slot.Right} cb.X:{cb.X} splitPos:{splitPos} m:{m}"); + } else { + splitIndex = -1; + for (int i = 0; i < Children.Count - 1; i++) + { + Rectangle r = Children[i].Slot; + if (m.X >= r.Right) { + r = Children[i+1].Slot; + if (m.X <= r.Left && Table.Columns.Count - 1 > i ) { + IFace.MouseCursor = MouseCursor.sb_h_double_arrow; + splitIndex = i; + e.Handled = true; + break; + } + } + } + if (splitIndex < 0 && IFace.MouseCursor == MouseCursor.sb_h_double_arrow) + IFace.MouseCursor = MouseCursor.top_left_arrow; + } + } + base.onMouseMove(sender, e); + } + } +} diff --git a/Crow/src/Widgets/TableRow.cs b/Crow/src/Widgets/TableRow.cs index dbb07661..1ce02c15 100644 --- a/Crow/src/Widgets/TableRow.cs +++ b/Crow/src/Widgets/TableRow.cs @@ -9,13 +9,11 @@ using Glfw; namespace Crow { - public class TableRow : HorizontalStack, ISelectable { + public class TableRow : GroupBase, ISelectable { #region ISelectable implementation bool isSelected; - public event EventHandler Selected; public event EventHandler Unselected; - [DefaultValue (false)] public virtual bool IsSelected { get { return isSelected; } @@ -33,173 +31,157 @@ namespace Crow } } #endregion + #region EVENT HANDLERS + public event EventHandler<EventArgs> ChildrenCleared; + #endregion + public override void ChildrenLayoutingConstraints(ILayoutable layoutable, ref LayoutingType layoutType) + => layoutType &= (~(LayoutingType.X|LayoutingType.Width)); - public Table Table => Parent as Table; - - /*public override void ChildrenLayoutingConstraints(ILayoutable layoutable, ref LayoutingType layoutType) - { - //trigger layouting for width only in the first row, the other will be set at the same horizontal position and width. - if (Table == null) { - base.ChildrenLayoutingConstraints (layoutable, ref layoutType); + public Table Table => Parent as Table; + internal Widget tallestChild = null; + public override void InsertChild (int idx, Widget g) { + if (disposed) { + DbgLogger.AddEvent (DbgEvtType.AlreadyDisposed | DbgEvtType.GOAddChild); return; } - if (this == Table.Children[0]) - layoutType &= (~LayoutingType.X); - else - layoutType &= (~(LayoutingType.X|LayoutingType.Width)); - }*/ - - public override void ComputeChildrenPositions () { - if (Children.Count == 0) - return; - int spacing = Table.Spacing; - ObservableList<Column> cols = Table.Columns; - - Widget first = Children[0]; - TableRow firstRow = Table.Children[0] as TableRow; - - if (firstRow == this) { - base.ComputeChildrenPositions(); - return; - } - childrenRWLock.EnterReadLock(); + childrenRWLock.EnterWriteLock (); + + g.Parent = this; + Children.Insert (idx, g); - for (int i = 0; i < Children.Count && i < firstRow.Children.Count; i++) - { - Widget w = Children[i]; - /*if (i < cols.Count && cols[i].Width.IsFit && cols[i].LargestWidget != null) { - w.Slot.X - }else{*/ - w.Slot.X = firstRow.Children[i].Slot.X; - setChildWidth (w, firstRow.Children[i].Slot.Width); - //} + childrenRWLock.ExitWriteLock (); + + if (g.LastSlots.Height > contentSize.Height) { + tallestChild = g; + contentSize.Height = g.LastSlots.Height; } - childrenRWLock.ExitReadLock(); - IsDirty = true; + + g.LayoutChanged += OnChildLayoutChanges; + g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); } - - public override bool UpdateLayout(LayoutingType layoutType) + public override void RemoveChild(Widget child) { - RegisteredLayoutings &= (~layoutType); + child.LayoutChanged -= OnChildLayoutChanges; + //check if HoverWidget is removed from Tree + if (IFace.HoverWidget != null) { + if (this.Contains (IFace.HoverWidget)) + IFace.HoverWidget = null; + } - if (Table == null) - return false; - TableRow firstRow = Table.Children[0] as TableRow; - if (layoutType == LayoutingType.Width) { - if (firstRow.RegisteredLayoutings.HasFlag (LayoutingType.Width)) - return false; - if (this != firstRow) { - Slot.Width = firstRow.Slot.Width; - if (Slot.Width != LastSlots.Width) { - IsDirty = true; - OnLayoutChanges (layoutType); - LastSlots.Width = Slot.Width; - } - if (RegisteredLayoutings == LayoutingType.None && IsDirty) - IFace.EnqueueForRepaint (this); + childrenRWLock.EnterWriteLock (); + + Children.Remove(child); + child.Parent = null; + child.LogicalParent = null; + + childrenRWLock.ExitWriteLock (); + + if (child == tallestChild && Height == Measure.Fit) + searchTallestChild (); + + this.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); - return true; - } - } - - return base.UpdateLayout(layoutType); } - /*public override int measureRawSize (LayoutingType lt) { - if (lt == LayoutingType.Width) { - if (Table == null) - return -1; - TableRow firstRow = Table.Children[0] as TableRow; - if (this != firstRow) { - if (firstRow.RegisteredLayoutings.HasFlag (LayoutingType.Width)) - return -1; - contentSize = firstRow.contentSize; - return firstRow.measureRawSize (lt); - } + public override void ClearChildren() + { + childrenRWLock.EnterWriteLock (); + while (Children.Count > 0) { + Widget g = Children [Children.Count - 1]; + g.LayoutChanged -= OnChildLayoutChanges; + Children.RemoveAt (Children.Count - 1); + g.Dispose (); } + + childrenRWLock.ExitWriteLock (); + + resetChildrenMaxSize (); + + RegisterForLayouting (LayoutingType.Sizing); + ChildrenCleared.Raise (this, new EventArgs ()); + } + public override int measureRawSize (LayoutingType lt) + { + if (lt == LayoutingType.Height && Children.Count > 0 && tallestChild == null) + searchTallestChild (); return base.measureRawSize (lt); - }*/ - /*public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { - if (arg.LayoutType == LayoutingType.Width) { - Widget w = sender as Widget; - TableRow firstRow = Table.Children[0] as TableRow; - int c = Children.IndexOf(w); - if (c < Table.Columns.Count) { - Column col = Table.Columns[c]; - if (col.Width.IsFit) { - if (col.LargestWidget == null || w.Slot.Width > col.ComputedWidth) { - col.ComputedWidth = w.Slot.Width; - col.LargestWidget = w; - } else if (w == col.LargestWidget) - Console.WriteLine ("must search for largest widget"); - }else if (w == firstRow) - col.ComputedWidth = w.Slot.Width; + } + public override void OnLayoutChanges (LayoutingType layoutType) + { + base.OnLayoutChanges (layoutType); + childrenRWLock.EnterReadLock (); + //position smaller objects in group when group size is fit + switch (layoutType) { + case LayoutingType.Height: + childrenRWLock.EnterReadLock (); + foreach (Widget c in Children) { + if (c.Height.IsRelativeToParent) + c.RegisterForLayouting (LayoutingType.Height); + else + c.RegisterForLayouting (LayoutingType.Y); } - Console.WriteLine ($"ROW:{Table.Children.IndexOf(this)} COL:{c} {w.LastSlots.Width} -> {w.Slot.Width} "); + childrenRWLock.ExitReadLock (); + break; } - base.OnChildLayoutChanges (sender, arg); - }*/ - /*public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { - Widget go = sender as Widget; - TableRow row = go.Parent as TableRow; - TableRow firstRow = Table.Children[0] as TableRow; + childrenRWLock.ExitReadLock (); + } + public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) + { + DbgLogger.StartEvent(DbgEvtType.GOOnChildLayoutChange, this); - if (arg.LayoutType == LayoutingType.Width) { - if (row == firstRow) { - base.OnChildLayoutChanges (sender, arg); - int idx = Children.IndexOf (go); - foreach (TableRow r in Table.Children.Skip(1)) { - if (idx < r.Children.Count) - r.setChildWidth (r.Children[idx], go.Slot.Width); - r.contentSize = firstRow.contentSize; - } - } //else - this.RegisterForLayouting (LayoutingType.ArrangeChildren); - return; + Widget g = sender as Widget; + + switch (arg.LayoutType) { + case LayoutingType.Height: + if (Height == Measure.Fit) { + if (g.Slot.Height > contentSize.Height) { + tallestChild = g; + contentSize.Height = g.Slot.Height; + } else if (g == tallestChild) + searchTallestChild (); + else + break; + this.RegisterForLayouting (LayoutingType.Height); + } + break; } + DbgLogger.EndEvent(DbgEvtType.GOOnChildLayoutChange); + } + protected virtual void searchTallestChild (bool forceMeasure = false) + { + DbgLogger.StartEvent (DbgEvtType.GOSearchTallestChild, this); + + childrenRWLock.EnterReadLock (); - base.OnChildLayoutChanges (sender, arg); - }*/ - int splitIndex = -1; - const int minColumnSize = 10; - public override void onMouseMove(object sender, MouseMoveEventArgs e) - { - if (Spacing > 0 && Table != null && Table.Children.Count > 0) { - Point m = ScreenPointToLocal (e.Position); - if (IFace.IsDown (Glfw.MouseButton.Left) && splitIndex >= 0) { - TableRow firstRow = Table.Children[0] as TableRow; - Rectangle cb = ClientRectangle; - int splitPos = (int)(0.5 * Spacing + m.X); - if (splitPos > firstRow.Children[splitIndex].Slot.Left + minColumnSize && splitPos < firstRow.Children[splitIndex+1].Slot.Right - minColumnSize) { - Table.Columns[splitIndex+1].Width = firstRow.Children[splitIndex+1].Slot.Right - splitPos; - splitPos -= Spacing; - Table.Columns[splitIndex].Width = splitPos - firstRow.Children[splitIndex].Slot.Left; - Table.RegisterForLayouting (LayoutingType.Width); - e.Handled = true; - } - //Console.WriteLine ($"left:{firstRow.Children[splitIndex].Slot.Left} right:{firstRow.Children[splitIndex+1].Slot.Right} cb.X:{cb.X} splitPos:{splitPos} m:{m}"); - } else { - splitIndex = -1; - for (int i = 0; i < Children.Count - 1; i++) - { - Rectangle r = Children[i].Slot; - if (m.X >= r.Right) { - r = Children[i+1].Slot; - if (m.X <= r.Left && Table.Columns.Count - 1 > i ) { - IFace.MouseCursor = MouseCursor.sb_h_double_arrow; - splitIndex = i; - e.Handled = true; - break; - } - } - } - if (splitIndex < 0 && IFace.MouseCursor == MouseCursor.sb_h_double_arrow) - IFace.MouseCursor = MouseCursor.top_left_arrow; + tallestChild = null; + contentSize.Height = 0; + for (int i = 0; i < Children.Count; i++) { + if (!Children [i].IsVisible) + continue; + int ch = 0; + if (forceMeasure) + ch = Children [i].measureRawSize (LayoutingType.Height); + else if (Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Height)) + continue; + else + ch = Children [i].Slot.Height; + if (ch > contentSize.Height) { + contentSize.Height = ch; + tallestChild = Children [i]; } } - base.onMouseMove(sender, e); + if (tallestChild == null && !forceMeasure) + searchTallestChild (true); + + childrenRWLock.ExitReadLock (); + + DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild); + } + void resetChildrenMaxSize(){ + tallestChild = null; + contentSize = 0; } } } diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index 47ac67f5..9f3f4781 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -911,18 +911,18 @@ namespace Crow if (value == isVisible) return; - isVisible = value; + isVisible = value; - if (!isVisible) + /*if (!isVisible) unshownPostActions (); - RegisterForLayouting (LayoutingType.Sizing); - - /*if (isVisible){ + RegisterForLayouting (LayoutingType.Sizing);*/ + + if (isVisible){ IsDirty = true; - RegisterForLayouting(LayoutingType.Sizing); } else { unshownPostActions (); - }*/ + } + RegisterForLayouting(LayoutingType.Sizing); NotifyValueChangedAuto (isVisible); @@ -1641,9 +1641,9 @@ namespace Crow if (LayoutChanged != null) LayoutChanged.Invoke (this, new LayoutingEventArgs (layoutType)); } - internal protected void raiseLayoutChanged(LayoutingEventArgs e){ + internal protected void raiseLayoutChanged(LayoutingType layoutingType){ if (LayoutChanged != null) - LayoutChanged.Raise (this, e); + LayoutChanged.Raise (this, new LayoutingEventArgs(layoutingType)); } /// <summary> Update layout component only one at a time, this is where the computation of alignement /// and size take place. @@ -1834,6 +1834,7 @@ namespace Crow DbgLogger.EndEvent (DbgEvtType.GORecreateCache); } protected void paintCache(Context ctx, Rectangle rb) { + DbgLogger.StartEvent(DbgEvtType.GOPaintCache, this); if (clearBackground) { ctx.Operator = Operator.Clear; ctx.Rectangle (rb); @@ -1843,10 +1844,12 @@ namespace Crow ctx.SetSource (bmp, rb.X, rb.Y); ctx.Paint (); + DbgLogger.EndEvent(DbgEvtType.GOPaintCache); } protected virtual void UpdateCache(Context ctx){ DbgLogger.StartEvent(DbgEvtType.GOUpdateCache, this); paintCache (ctx, Slot + Parent.ClientRectangle.Position); + DbgLogger.AddEvent (DbgEvtType.GOResetClip, this); Clipping.Reset (); DbgLogger.EndEvent (DbgEvtType.GOUpdateCache); } @@ -1854,8 +1857,8 @@ namespace Crow /// of the widget </summary> public virtual void Paint (Context ctx) { - if (!IsVisible) - return; + /*if (!IsVisible) + return;*/ DbgLogger.StartEvent (DbgEvtType.GOPaint, this); @@ -2146,19 +2149,19 @@ namespace Crow /// Checks to handle when widget is removed from the visible graphic tree /// </summary> void unshownPostActions () { - //IsDirty = true; + IsDirty = true; /*if (parent is Widget p) p.RegisterForGraphicUpdate(); else*/ - /*try + try { parent?.RegisterClip (ContextCoordinates(LastPaintedSlot)); } catch (System.Exception e) { Debug.WriteLine($"[ERR]:unshownPostActions:{e}"); - }*/ + } if (IFace.ActiveWidget != null) { @@ -2199,7 +2202,7 @@ namespace Crow } LastSlots = default; LastPaintedSlot = default;*/ - + //Slot = LastSlots = default; } } } |