diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-06-16 16:00:50 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-06-16 16:00:50 +0200 |
| commit | 5115f379fc240b1250220910b14d69bb27a32c1e (patch) | |
| tree | 1818ebcf5f2f5bd2f9730d85391217fcd1038c92 | |
| parent | 58e1683bdbe1c169a1ab18b170283f8d171049a7 (diff) | |
using try/finally to ensure mutexes release
31 files changed, 630 insertions, 664 deletions
diff --git a/Crow/src/DebugUtils/DebugLogger.cs b/Crow/src/DebugUtils/DebugLogger.cs index 2a9b75bb..e048008f 100644 --- a/Crow/src/DebugUtils/DebugLogger.cs +++ b/Crow/src/DebugUtils/DebugLogger.cs @@ -25,7 +25,7 @@ namespace Crow static bool logevt (DbgEvtType evtType) //=> IncludeEvents != DbgEvtType.None && (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) == IncludeEvents; //=> IncludeEvents != DbgEvtType.None && (evtType & DiscardEvents) == 0 && (evtType & IncludeEvents) == IncludeEvents; - => IncludeEvents == DbgEvtType.All || (IncludeEvents != DbgEvtType.None && (evtType & IncludeEvents) == IncludeEvents); + => IncludeEvents == DbgEvtType.All || (IncludeEvents != DbgEvtType.None && (evtType & IncludeEvents) != 0); diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index d39121b0..8755d817 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -924,20 +924,23 @@ namespace Crow DbgLogger.StartEvent (DbgEvtType.Update); PerformanceMeasure.Begin (PerformanceMeasure.Kind.Update); - processLayouting (); + try { + processLayouting (); - clippingRegistration (); + clippingRegistration (); - if (ctx == null) { - using (ctx = new Context (surf)) + if (ctx == null) { + using (ctx = new Context (surf)) + processDrawing (ctx); + }else processDrawing (ctx); - }else - processDrawing (ctx); + } finally { - PerformanceMeasure.End (PerformanceMeasure.Kind.Update); - DbgLogger.EndEvent (DbgEvtType.Update, true); + PerformanceMeasure.End (PerformanceMeasure.Kind.Update); + DbgLogger.EndEvent (DbgEvtType.Update, true); - Monitor.Exit (UpdateMutex); + Monitor.Exit (UpdateMutex); + } PerformanceMeasure.Notify (); } @@ -950,23 +953,23 @@ namespace Crow Monitor.Exit (LayoutMutex); return; } + DbgLogger.StartEvent (DbgEvtType.ProcessLayouting); PerformanceMeasure.Begin (PerformanceMeasure.Kind.Layouting); + try { + DiscardQueue = new Queue<LayoutingQueueItem> (LayoutingQueue.Count); + while (LayoutingQueue.Count > 0) { + LayoutingQueueItem lqi = LayoutingQueue.Dequeue (); + lqi.ProcessLayouting (); + } + LayoutingQueue = DiscardQueue; + } finally { + PerformanceMeasure.End (PerformanceMeasure.Kind.Layouting); + DbgLogger.EndEvent (DbgEvtType.ProcessLayouting, true); - DiscardQueue = new Queue<LayoutingQueueItem> (LayoutingQueue.Count); - //Debug.WriteLine ("======= Layouting queue start ======="); - - while (LayoutingQueue.Count > 0) { - LayoutingQueueItem lqi = LayoutingQueue.Dequeue (); - lqi.ProcessLayouting (); + Monitor.Exit (LayoutMutex); + DiscardQueue = null; } - LayoutingQueue = DiscardQueue; - - PerformanceMeasure.End (PerformanceMeasure.Kind.Layouting); - DbgLogger.EndEvent (DbgEvtType.ProcessLayouting, true); - - Monitor.Exit (LayoutMutex); - DiscardQueue = null; } } /// <summary>Degueue Widget to clip from DrawingQueue and register the last painted slot and the new one @@ -1005,7 +1008,6 @@ namespace Crow ctx.PushGroup (); - for (int i = GraphicTree.Count -1; i >= 0 ; i--){ Widget p = GraphicTree[i]; if (!p.IsVisible) diff --git a/Crow/src/LayoutingQueueItem.cs b/Crow/src/LayoutingQueueItem.cs index c6aa6dc6..3cfdaa47 100644 --- a/Crow/src/LayoutingQueueItem.cs +++ b/Crow/src/LayoutingQueueItem.cs @@ -82,55 +82,54 @@ namespace Crow public void ProcessLayouting() { Widget go = Layoutable as Widget; -// if (go == null) { -// Debug.WriteLine ("ERROR: processLayouting on something else than a graphic object: " + this.ToString ()); -// return; -// } + DbgLogger.StartEvent (DbgEvtType.GOProcessLayouting, this); go.parentRWLock.EnterReadLock (); - if (go.Parent == null) {//TODO:improve this - //cancel layouting for object without parent, maybe some were in queue when - //removed from a listbox - DbgLogger.AddEvent (DbgEvtType.GOProcessLayoutingWithNoParent, this); - go.parentRWLock.ExitReadLock (); - return; - } + try { + + if (go.Parent == null) {//TODO:improve this + //cancel layouting for object without parent, maybe some were in queue when + //removed from a listbox + DbgLogger.AddEvent (DbgEvtType.GOProcessLayoutingWithNoParent, this); + return; + } #if DEBUG_LOG - DbgLogger.StartEvent (DbgEvtType.GOProcessLayouting, this); - Slot = graphicObject.Slot; + Slot = graphicObject.Slot; #endif - LayoutingTries++; - if (!Layoutable.UpdateLayout (LayoutType)) { - if (LayoutingTries < Interface.MaxLayoutingTries) { - Layoutable.RegisteredLayoutings |= LayoutType; - (Layoutable as Widget).IFace.LayoutingQueue.Enqueue (this); + LayoutingTries++; + if (!Layoutable.UpdateLayout (LayoutType)) { + if (LayoutingTries < Interface.MaxLayoutingTries) { + Layoutable.RegisteredLayoutings |= LayoutType; + (Layoutable as Widget).IFace.LayoutingQueue.Enqueue (this); #if DEBUG_LOG - result = Result.Requeued; + result = Result.Requeued; #endif - } else if (DiscardCount < Interface.MaxDiscardCount) { + } else if (DiscardCount < Interface.MaxDiscardCount) { #if DEBUG_LOG - result = Result.Discarded; + result = Result.Discarded; +#endif + LayoutingTries = 0; + DiscardCount++; + Layoutable.RegisteredLayoutings |= LayoutType; + (Layoutable as Widget).IFace.DiscardQueue.Enqueue (this); + } +#if DEBUG_LOG + else { + result = Result.Deleted; + } #endif - LayoutingTries = 0; - DiscardCount++; - Layoutable.RegisteredLayoutings |= LayoutType; - (Layoutable as Widget).IFace.DiscardQueue.Enqueue (this); } #if DEBUG_LOG - else { - result = Result.Deleted; + else{ + result = Result.Success; } + NewSlot = graphicObject.Slot; #endif + }finally { + go.parentRWLock.ExitReadLock (); + DbgLogger.EndEvent (DbgEvtType.GOProcessLayouting, this); } -#if DEBUG_LOG - else{ - result = Result.Success; - } - NewSlot = graphicObject.Slot; - DbgLogger.EndEvent (DbgEvtType.GOProcessLayouting, this); -#endif - go.parentRWLock.ExitReadLock (); } public static implicit operator Widget(LayoutingQueueItem queueItem) => queueItem.Layoutable as Widget; diff --git a/Crow/src/Widgets/DockStack.cs b/Crow/src/Widgets/DockStack.cs index d72270c7..41c7f8b4 100644 --- a/Crow/src/Widgets/DockStack.cs +++ b/Crow/src/Widgets/DockStack.cs @@ -79,15 +79,18 @@ namespace Crow Rectangle cb = ClientRectangle; childrenRWLock.EnterReadLock (); - foreach (Widget c in Children) { - Rectangle bounds = c.Slot + cb.Position; - if (!bounds.ContainsOrIsEqual (lm)) - continue; - rIn = bounds; - focusedChild = c; - break; + try { + foreach (Widget c in Children) { + Rectangle bounds = c.Slot + cb.Position; + if (!bounds.ContainsOrIsEqual (lm)) + continue; + rIn = bounds; + focusedChild = c; + break; + } + } finally { + childrenRWLock.ExitReadLock (); } - childrenRWLock.ExitReadLock (); } public void onDragMouseMove (object sender, MouseMoveEventArgs e) diff --git a/Crow/src/Widgets/Group.cs b/Crow/src/Widgets/Group.cs index 9e78f187..a2a58b7f 100644 --- a/Crow/src/Widgets/Group.cs +++ b/Crow/src/Widgets/Group.cs @@ -35,12 +35,13 @@ namespace Crow } childrenRWLock.EnterWriteLock (); - - Children.Remove(child); - child.Parent = null; - child.LogicalParent = null; - - childrenRWLock.ExitWriteLock (); + try { + Children.Remove(child); + child.Parent = null; + child.LogicalParent = null; + } finally { + childrenRWLock.ExitWriteLock (); + } if (child == largestChild && Width == Measure.Fit) searchLargestChild (); @@ -56,14 +57,15 @@ namespace Crow return; } childrenRWLock.EnterWriteLock (); - - g.Parent = this; - Children.Insert (idx, g); - - childrenRWLock.ExitWriteLock (); + try { + g.Parent = this; + Children.Insert (idx, g); + } finally { + childrenRWLock.ExitWriteLock (); + } //largestChild = tallestChild = null; - if (g.LastSlots.Width > contentSize.Width) { + if (g.LastSlots.Width > contentSize.Width) {//TODO:Layout mutex? largestChild = g; contentSize.Width = g.LastSlots.Width; } @@ -79,16 +81,17 @@ namespace Crow 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 (); + try { + while (Children.Count > 0) { + Widget g = Children [Children.Count - 1]; + g.LayoutChanged -= OnChildLayoutChanges; + Children.RemoveAt (Children.Count - 1); + g.Dispose (); + } + } finally { + childrenRWLock.ExitWriteLock (); } - childrenRWLock.ExitWriteLock (); - resetChildrenMaxSize (); RegisterForLayouting (LayoutingType.Sizing); @@ -117,30 +120,33 @@ namespace Crow base.OnLayoutChanges (layoutType); childrenRWLock.EnterReadLock (); - //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); + try { + //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 (); - break; + } finally { + childrenRWLock.ExitReadLock (); } - childrenRWLock.ExitReadLock (); } #endregion public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) @@ -177,7 +183,7 @@ namespace Crow } DbgLogger.EndEvent(DbgEvtType.GOOnChildLayoutChange); } - //TODO: x,y position should be taken in account for computation of width and height + //TODO: x,y position should be taken in account for computation of width and height + Layout mutex? void resetChildrenMaxSize(){ largestChild = null; tallestChild = null; @@ -186,62 +192,63 @@ namespace Crow 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++) { - if (!Children [i].IsVisible) - continue; - int cw = 0; - if (forceMeasure) - cw = Children [i].measureRawSize (LayoutingType.Width); - else if (Children[i].Width.IsRelativeToParent || Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Width)) - continue; - else - cw = Children [i].Slot.Width; - if (cw > contentSize.Width) { - contentSize.Width = cw; - largestChild = Children [i]; + try { + + largestChild = null; + contentSize.Width = 0; + for (int i = 0; i < Children.Count; i++) { + if (!Children [i].IsVisible) + continue; + int cw = 0; + if (forceMeasure) + cw = Children [i].measureRawSize (LayoutingType.Width); + else if (Children[i].Width.IsRelativeToParent || Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Width)) + continue; + else + cw = Children [i].Slot.Width; + if (cw > contentSize.Width) { + contentSize.Width = cw; + largestChild = Children [i]; + } } + if (largestChild == null && !forceMeasure) + searchLargestChild (true); + } finally { + childrenRWLock.ExitReadLock (); + DbgLogger.EndEvent (DbgEvtType.GOSearchLargestChild); } - if (largestChild == null && !forceMeasure) - searchLargestChild (true); - - childrenRWLock.ExitReadLock (); - - DbgLogger.EndEvent (DbgEvtType.GOSearchLargestChild); } 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++) { - if (!Children [i].IsVisible) - continue; - int ch = 0; - if (forceMeasure) - ch = Children [i].measureRawSize (LayoutingType.Height); - else if (Children[i].Height.IsRelativeToParent || Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Height)) - continue; - else - ch = Children [i].Slot.Height; - if (ch > contentSize.Height) { - contentSize.Height = ch; - tallestChild = Children [i]; + try { + 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].Height.IsRelativeToParent || Children [i].RegisteredLayoutings.HasFlag (LayoutingType.Height)) + continue; + else + ch = Children [i].Slot.Height; + if (ch > contentSize.Height) { + contentSize.Height = ch; + tallestChild = Children [i]; + } } + if (tallestChild == null && !forceMeasure) + searchTallestChild (true); + } finally { + childrenRWLock.ExitReadLock (); + DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild); } - if (tallestChild == null && !forceMeasure) - searchTallestChild (true); - - childrenRWLock.ExitReadLock (); - - DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild); } } } diff --git a/Crow/src/Widgets/GroupBase.cs b/Crow/src/Widgets/GroupBase.cs index 5784bc29..cac017c7 100644 --- a/Crow/src/Widgets/GroupBase.cs +++ b/Crow/src/Widgets/GroupBase.cs @@ -20,14 +20,15 @@ namespace Crow if (base.FindByDesignID (designID, out go)) return true; childrenRWLock.EnterReadLock (); - foreach (Widget w in Children) { - if (!w.FindByDesignID (designID, out go)) - continue; + try { + foreach (Widget w in Children) { + if (w.FindByDesignID (designID, out go)) + return true; + } + return false; + } finally { childrenRWLock.ExitReadLock (); - return true; } - childrenRWLock.ExitReadLock (); - return false; } public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem) { @@ -73,12 +74,13 @@ namespace Crow } childrenRWLock.EnterWriteLock (); - - Children.Remove(child); - child.Parent = null; - child.LogicalParent = null; - - childrenRWLock.ExitWriteLock (); + try { + Children.Remove(child); + child.Parent = null; + child.LogicalParent = null; + } finally { + childrenRWLock.ExitWriteLock (); + } } public virtual void DeleteChild(Widget child) { @@ -91,11 +93,12 @@ namespace Crow return; } childrenRWLock.EnterWriteLock (); - - g.Parent = this; - Children.Insert (idx, g); - - childrenRWLock.ExitWriteLock (); + try { + g.Parent = this; + Children.Insert (idx, g); + } finally { + childrenRWLock.ExitWriteLock (); + } } public virtual void RemoveChild (int idx) { RemoveChild (children[idx]); @@ -107,53 +110,57 @@ namespace Crow { childrenRWLock.EnterWriteLock (); - while (Children.Count > 0) { - Widget g = Children [Children.Count - 1]; - Children.RemoveAt (Children.Count - 1); - g.Dispose (); + try { + while (Children.Count > 0) { + Widget g = Children [Children.Count - 1]; + Children.RemoveAt (Children.Count - 1); + g.Dispose (); + } + } finally { + childrenRWLock.ExitWriteLock (); } - - childrenRWLock.ExitWriteLock (); } public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) { base.OnDataSourceChanged (this, e); + + childrenRWLock.EnterReadLock (); try { - childrenRWLock.EnterReadLock (); foreach (Widget g in Children) { if (g.localDataSourceIsNull & g.localLogicalParentIsNull) g.OnDataSourceChanged (g, e); } + } finally { childrenRWLock.ExitReadLock (); - } catch (Exception) { - childrenRWLock.ExitReadLock (); - throw; } } public void putWidgetOnTop(Widget w) { - if (Children.Contains(w)) - { - childrenRWLock.EnterWriteLock (); - - Children.Remove (w); - Children.Add (w); - + childrenRWLock.EnterWriteLock (); + try { + if (Children.Contains(w)) + { + Children.Remove (w); + Children.Add (w); + } + } finally { childrenRWLock.ExitWriteLock (); } } + public void putWidgetOnBottom(Widget w) { - if (Children.Contains(w)) - { - childrenRWLock.EnterWriteLock (); - - Children.Remove (w); - Children.Insert (0, w); - + childrenRWLock.EnterWriteLock (); + try { + if (Children.Contains(w)) + { + Children.Remove (w); + Children.Insert (0, w); + } + } finally { childrenRWLock.ExitWriteLock (); - } + } } #region GraphicObject overrides @@ -165,15 +172,18 @@ namespace Crow childrenRWLock.EnterReadLock (); - foreach (Widget w in Children) { - tmp = w.FindByName (nameToFind); - if (tmp != null) - break; - } + try { - childrenRWLock.ExitReadLock (); + foreach (Widget w in Children) { + tmp = w.FindByName (nameToFind); + if (tmp != null) + break; + } + return tmp; - return tmp; + } finally { + childrenRWLock.ExitReadLock (); + } } public override T FindByType<T> () { @@ -195,13 +205,18 @@ namespace Crow } public override bool Contains (Widget goToFind) { - foreach (Widget w in Children) { - if (w == goToFind) - return true; - if (w.Contains (goToFind)) - return true; + childrenRWLock.EnterReadLock (); + try { + foreach (Widget w in Children) { + if (w == goToFind) + return true; + if (w.Contains (goToFind)) + return true; + } + return false; + } finally { + childrenRWLock.ExitReadLock (); } - return false; } protected override void onDraw (Context gr) @@ -217,20 +232,14 @@ namespace Crow gr.Clip (); } + childrenRWLock.EnterReadLock (); try { - childrenRWLock.EnterReadLock (); - for (int i = 0; i < Children.Count; i++) - Children[i].Paint (gr); - + Children[i].Paint (gr); + } finally { childrenRWLock.ExitReadLock (); } - catch (System.Exception) - { - childrenRWLock.ExitReadLock (); - throw; - } if (ClipToClientRect) gr.Restore (); @@ -257,17 +266,18 @@ namespace Crow } childrenRWLock.EnterReadLock (); - - foreach (Widget c in Children) { - if (!c.IsVisible) - continue; - if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out) - continue; - c.Paint (gr); + try { + foreach (Widget c in Children) { + if (!c.IsVisible) + continue; + if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out) + continue; + c.Paint (gr); + } + } finally { + childrenRWLock.ExitReadLock (); } - childrenRWLock.ExitReadLock (); - #if DEBUG_CLIP_RECTANGLE /*gr.LineWidth = 1; gr.SetSourceColor(Color.DarkMagenta.AdjustAlpha (0.8)); @@ -290,14 +300,16 @@ namespace Crow base.checkHoverWidget (e);//TODO:check if not possible to put it at beginning of meth to avoid doubled check to DropTarget. if (!childrenRWLock.TryEnterReadLock (10)) return; - for (int i = Children.Count - 1; i >= 0; i--) { - if (Children[i].MouseIsIn (e.Position)) { - Children[i].checkHoverWidget (e); - childrenRWLock.ExitReadLock (); - return; + try { + for (int i = Children.Count - 1; i >= 0; i--) { + if (Children[i].MouseIsIn (e.Position)) { + Children[i].checkHoverWidget (e); + return; + } } + } finally { + childrenRWLock.ExitReadLock (); } - childrenRWLock.ExitReadLock (); } #endregion @@ -305,9 +317,12 @@ namespace Crow { if (disposing) { childrenRWLock.EnterReadLock (); - foreach (Widget c in Children) - c.Dispose (); - childrenRWLock.ExitReadLock (); + try { + foreach (Widget c in Children) + c.Dispose (); + } finally { + childrenRWLock.ExitReadLock (); + } } base.Dispose (disposing); } diff --git a/Crow/src/Widgets/Label.cs b/Crow/src/Widgets/Label.cs index 17544ec7..31127ddd 100644 --- a/Crow/src/Widgets/Label.cs +++ b/Crow/src/Widgets/Label.cs @@ -611,9 +611,12 @@ namespace Crow if (!System.Threading.Monitor.TryEnter (linesMutex)) return false; } - bool result = base.UpdateLayout (layoutType); - System.Threading.Monitor.Exit (linesMutex); - return result; + try { + bool result = base.UpdateLayout (layoutType); + return result; + } finally { + System.Threading.Monitor.Exit (linesMutex); + } } public override int measureRawSize(LayoutingType lt) { diff --git a/Crow/src/Widgets/ScrollingStack.cs b/Crow/src/Widgets/ScrollingStack.cs index 959a4550..b00bb211 100644 --- a/Crow/src/Widgets/ScrollingStack.cs +++ b/Crow/src/Widgets/ScrollingStack.cs @@ -114,10 +114,8 @@ namespace Crow { gr.Clip (); } - try - { - childrenRWLock.EnterReadLock (); - + childrenRWLock.EnterReadLock (); + try { for (int i = Scroll; i < Children.Count && i < Scroll + visibleItems; i++) { if (!Children[i].IsVisible) continue; @@ -125,13 +123,8 @@ namespace Crow { continue;*/ Children[i].Paint (gr); } - - childrenRWLock.ExitReadLock (); - } - catch (System.Exception) - { + } finally { childrenRWLock.ExitReadLock (); - throw; } if (ClipToClientRect) @@ -159,17 +152,18 @@ namespace Crow { } childrenRWLock.EnterReadLock (); - - for (int i = Scroll; i < Children.Count && i < Scroll + visibleItems; i++) { - if (!Children[i].IsVisible) - continue; - /*if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out) - continue;*/ - Children[i].Paint (gr); + try { + for (int i = Scroll; i < Children.Count && i < Scroll + visibleItems; i++) { + if (!Children[i].IsVisible) + continue; + /*if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out) + continue;*/ + Children[i].Paint (gr); + } + } finally { + childrenRWLock.ExitReadLock (); } - childrenRWLock.ExitReadLock (); - #if DEBUG_CLIP_RECTANGLE /*gr.LineWidth = 1; gr.SetSourceColor(Color.DarkMagenta.AdjustAlpha (0.8)); @@ -191,14 +185,16 @@ namespace Crow { base.checkHoverWidget (e);//TODO:check if not possible to put it at beginning of meth to avoid doubled check to DropTarget. if (!childrenRWLock.TryEnterReadLock (10)) return; - for (int i = Children.Count - 1; i >= 0; i--) { - if (Children[i].MouseIsIn (e.Position)) { - Children[i].checkHoverWidget (e); - childrenRWLock.ExitReadLock (); - return; + try { + for (int i = Children.Count - 1; i >= 0; i--) { + if (Children[i].MouseIsIn (e.Position)) { + Children[i].checkHoverWidget (e); + return; + } } + } finally { + childrenRWLock.ExitReadLock (); } - childrenRWLock.ExitReadLock (); } /// <summary> Process scrolling vertically, or if shift is down, vertically </summary> public override void onMouseWheel (object sender, MouseWheelEventArgs e) { diff --git a/Crow/src/Widgets/Table.cs b/Crow/src/Widgets/Table.cs index 27cfb963..1427e9ba 100644 --- a/Crow/src/Widgets/Table.cs +++ b/Crow/src/Widgets/Table.cs @@ -265,29 +265,30 @@ namespace Crow Column c = Columns[cIdx]; childrenRWLock.EnterReadLock (); - - 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]; + try { + 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]; + } } + if (HeaderRow.Children[cIdx].Slot.Width > largestWidth) { + c.LargestChild = HeaderRow.Children[cIdx]; + return; + } + HeaderRow.Children[cIdx].Slot.Width = largestWidth; + } finally { + childrenRWLock.ExitReadLock (); + DbgLogger.EndEvent (DbgEvtType.GOSearchLargestChild); } - childrenRWLock.ExitReadLock (); - - 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; diff --git a/Crow/src/Widgets/TableRow.cs b/Crow/src/Widgets/TableRow.cs index 1ce02c15..1f646bcb 100644 --- a/Crow/src/Widgets/TableRow.cs +++ b/Crow/src/Widgets/TableRow.cs @@ -45,11 +45,13 @@ namespace Crow return; } childrenRWLock.EnterWriteLock (); - - g.Parent = this; - Children.Insert (idx, g); - - childrenRWLock.ExitWriteLock (); + + try { + g.Parent = this; + Children.Insert (idx, g); + } finally { + childrenRWLock.ExitWriteLock (); + } if (g.LastSlots.Height > contentSize.Height) { tallestChild = g; @@ -70,12 +72,13 @@ namespace Crow } childrenRWLock.EnterWriteLock (); - - Children.Remove(child); - child.Parent = null; - child.LogicalParent = null; - - childrenRWLock.ExitWriteLock (); + try { + Children.Remove(child); + child.Parent = null; + child.LogicalParent = null; + } finally { + childrenRWLock.ExitWriteLock (); + } if (child == tallestChild && Height == Measure.Fit) searchTallestChild (); @@ -86,16 +89,17 @@ namespace Crow 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 (); + try { + while (Children.Count > 0) { + Widget g = Children [Children.Count - 1]; + g.LayoutChanged -= OnChildLayoutChanges; + Children.RemoveAt (Children.Count - 1); + g.Dispose (); + } + } finally { + childrenRWLock.ExitWriteLock (); } - childrenRWLock.ExitWriteLock (); - resetChildrenMaxSize (); RegisterForLayouting (LayoutingType.Sizing); @@ -111,21 +115,20 @@ namespace Crow { base.OnLayoutChanges (layoutType); - childrenRWLock.EnterReadLock (); //position smaller objects in group when group size is fit - switch (layoutType) { - case LayoutingType.Height: + if (layoutType == LayoutingType.Height) { childrenRWLock.EnterReadLock (); - foreach (Widget c in Children) { - if (c.Height.IsRelativeToParent) - c.RegisterForLayouting (LayoutingType.Height); - else - c.RegisterForLayouting (LayoutingType.Y); + try { + foreach (Widget c in Children) { + if (c.Height.IsRelativeToParent) + c.RegisterForLayouting (LayoutingType.Height); + else + c.RegisterForLayouting (LayoutingType.Y); + } + } finally { + childrenRWLock.ExitReadLock (); } - childrenRWLock.ExitReadLock (); - break; } - childrenRWLock.ExitReadLock (); } public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { @@ -152,32 +155,32 @@ namespace Crow 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++) { - 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]; + try { + 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]; + } } + if (tallestChild == null && !forceMeasure) + searchTallestChild (true); + } finally { + childrenRWLock.ExitReadLock (); + DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild); } - if (tallestChild == null && !forceMeasure) - searchTallestChild (true); - - childrenRWLock.ExitReadLock (); - - DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild); } void resetChildrenMaxSize(){ tallestChild = null; diff --git a/Crow/src/Widgets/TemplatedGroup.cs b/Crow/src/Widgets/TemplatedGroup.cs index f489ca96..90c23553 100644 --- a/Crow/src/Widgets/TemplatedGroup.cs +++ b/Crow/src/Widgets/TemplatedGroup.cs @@ -365,14 +365,14 @@ namespace Crow { try { loadPage (data, itemsContainer, dataTest); } catch (Exception ex) { - while (Monitor.IsEntered (IFace.UpdateMutex)) +/* while (Monitor.IsEntered (IFace.UpdateMutex)) Monitor.Exit (IFace.UpdateMutex); while (Monitor.IsEntered (IFace.LayoutMutex)) - Monitor.Exit (IFace.LayoutMutex); + Monitor.Exit (IFace.LayoutMutex);*/ System.Diagnostics.Debug.WriteLine ("loading thread aborted: " + ex.ToString()); + } finally { + DbgLogger.EndEvent (DbgEvtType.TGLoadingThread); } - - DbgLogger.EndEvent (DbgEvtType.TGLoadingThread); } // //if (!ItemTemplates.ContainsKey ("default")) // // ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate); @@ -392,7 +392,7 @@ namespace Crow { DbgLogger.StartEvent (DbgEvtType.TGCancelLoadingThread, this); - int updateMx = 0, layoutMx = 0; + /*int updateMx = 0, layoutMx = 0; while (Monitor.IsEntered (IFace.UpdateMutex)) { Monitor.Exit (IFace.UpdateMutex); @@ -401,14 +401,14 @@ namespace Crow { while (Monitor.IsEntered (IFace.LayoutMutex)) { Monitor.Exit (IFace.LayoutMutex); layoutMx++; - } + }*/ loadingThread.Cancel (); - for (int i = 0; i < layoutMx; i++) + /*for (int i = 0; i < layoutMx; i++) Monitor.Enter (IFace.LayoutMutex); for (int i = 0; i < updateMx; i++) - Monitor.Enter (IFace.UpdateMutex); + Monitor.Enter (IFace.UpdateMutex);*/ loadingThread = null; @@ -500,6 +500,7 @@ namespace Crow { } } + try { g = iTemp.CreateInstance(); #if DESIGN_MODE g.design_isTGItem = true; @@ -508,7 +509,9 @@ namespace Crow { // if (isPaged) g.LogicalParent = this; g.MouseClick += itemClick; - Monitor.Exit (IFace.UpdateMutex); + } finally { + Monitor.Exit (IFace.UpdateMutex); + } if (iTemp.Expand != null) { IToggle toggle = g as IToggle; diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index dbed07b7..d47675b8 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -332,7 +332,7 @@ namespace Crow /// Parent in the graphic tree, used for rendering and layouting /// </summary> [XmlIgnore]public virtual ILayoutable Parent { - get { return parent; } + get => parent; set { if (parent == value) return; @@ -1012,12 +1012,12 @@ namespace Crow if (value != null) rootDataLevel = true; - DbgLogger.StartEvent(DbgEvtType.GOLockUpdate, this); - lock (IFace.UpdateMutex) { + /*DbgLogger.StartEvent(DbgEvtType.GOLockUpdate, this); + lock (IFace.UpdateMutex) {*/ OnDataSourceChanged (this, dse); NotifyValueChangedAuto (DataSource); - } - DbgLogger.EndEvent (DbgEvtType.GOLockUpdate); + /*} + DbgLogger.EndEvent (DbgEvtType.GOLockUpdate);*/ } get { return rootDataLevel ? dataSource : dataSource == null ? @@ -1456,8 +1456,8 @@ namespace Crow parentRWLock.EnterReadLock (); if (parent != null) { - Parent.RegisterClip (LastPaintedSlot); - Parent.RegisterClip (Slot); + parent.RegisterClip (LastPaintedSlot); + parent.RegisterClip (Slot); } parentRWLock.ExitReadLock (); @@ -1473,30 +1473,26 @@ namespace Crow return; } DbgLogger.StartEvent(DbgEvtType.GORegisterClip, this); - Rectangle cb = ClientRectangle; - Rectangle r = clip + cb.Position; - if (r.Right > cb.Right) - r.Width -= r.Right - cb.Right; - if (r.Bottom > cb.Bottom) - r.Height -= r.Bottom - cb.Bottom; - if (r.Width < 0 || r.Height < 0) { - //Debug.WriteLine ($"Invalid clip: {clip}:{r} hnd:{this}");//\n{Environment.StackTrace}"); - DbgLogger.EndEvent (DbgEvtType.GORegisterClip); - return; - } - if (cacheEnabled && !IsDirty) - Clipping.UnionRectangle (r); - if (Parent == null) { - DbgLogger.EndEvent (DbgEvtType.GORegisterClip); - return; - } - Widget p = Parent as Widget; - if (p?.IsDirty == true && p?.CacheEnabled == true) { + try { + Rectangle cb = ClientRectangle; + Rectangle r = clip + cb.Position; + if (r.Right > cb.Right) + r.Width -= r.Right - cb.Right; + if (r.Bottom > cb.Bottom) + r.Height -= r.Bottom - cb.Bottom; + if (r.Width < 0 || r.Height < 0) + return; + if (cacheEnabled && !IsDirty) + Clipping.UnionRectangle (r); + if (Parent == null) + return; + Widget p = Parent as Widget; + if (p?.IsDirty == true && p?.CacheEnabled == true) + return; + Parent.RegisterClip (r + Slot.Position); + } finally { DbgLogger.EndEvent (DbgEvtType.GORegisterClip); - return; } - Parent.RegisterClip (r + Slot.Position); - DbgLogger.EndEvent (DbgEvtType.GORegisterClip); } /// <summary> Full update, if width or height is 'Fit' a layouting is requested, and a redraw is done in any case. </summary> [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1580,47 +1576,47 @@ namespace Crow if (Parent == null) return; DbgLogger.StartEvent (DbgEvtType.GOLockLayouting, this); - lock (IFace.LayoutMutex) { - //prevent queueing same LayoutingType for this - layoutType &= (~RegisteredLayoutings); + try { + lock (IFace.LayoutMutex) { + //prevent queueing same LayoutingType for this + layoutType &= (~RegisteredLayoutings); - if (layoutType == LayoutingType.None) { - DbgLogger.EndEvent (DbgEvtType.GOLockLayouting); - return; - } - //dont set position for stretched item - if (Width == Measure.Stretched) - layoutType &= (~LayoutingType.X); - if (Height == Measure.Stretched) - layoutType &= (~LayoutingType.Y); + if (layoutType == LayoutingType.None) + return; + + //dont set position for stretched item + if (Width == Measure.Stretched) + layoutType &= (~LayoutingType.X); + if (Height == Measure.Stretched) + layoutType &= (~LayoutingType.Y); - if (!ArrangeChildren) - layoutType &= (~LayoutingType.ArrangeChildren); + if (!ArrangeChildren) + layoutType &= (~LayoutingType.ArrangeChildren); - //apply constraints depending on parent type - Parent.ChildrenLayoutingConstraints (this, ref layoutType); + //apply constraints depending on parent type + Parent.ChildrenLayoutingConstraints (this, ref layoutType); -// //prevent queueing same LayoutingType for this - layoutType &= (~RegisteredLayoutings); + // //prevent queueing same LayoutingType for this + layoutType &= (~RegisteredLayoutings); - if (layoutType == LayoutingType.None) { - DbgLogger.EndEvent (DbgEvtType.GOLockLayouting); - return; - } + if (layoutType == LayoutingType.None) + return; - //enqueue LQI LayoutingTypes separately - if (layoutType.HasFlag (LayoutingType.Width)) - IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Width, this)); - if (layoutType.HasFlag (LayoutingType.Height)) - IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Height, this)); - if (layoutType.HasFlag (LayoutingType.X)) - IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.X, this)); - if (layoutType.HasFlag (LayoutingType.Y)) - IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Y, this)); - if (layoutType.HasFlag (LayoutingType.ArrangeChildren)) - IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this)); + //enqueue LQI LayoutingTypes separately + if (layoutType.HasFlag (LayoutingType.Width)) + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Width, this)); + if (layoutType.HasFlag (LayoutingType.Height)) + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Height, this)); + if (layoutType.HasFlag (LayoutingType.X)) + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.X, this)); + if (layoutType.HasFlag (LayoutingType.Y)) + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Y, this)); + if (layoutType.HasFlag (LayoutingType.ArrangeChildren)) + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this)); + } + } finally { + DbgLogger.EndEvent (DbgEvtType.GOLockLayouting); } - DbgLogger.EndEvent (DbgEvtType.GOLockLayouting); } /// <summary> trigger dependant sizing component update </summary> @@ -1888,11 +1884,11 @@ namespace Crow DbgLogger.EndEvent (DbgEvtType.GOPaint); return; } - lock (this) { + //lock (this) { if (cacheEnabled) { if (Slot.Width > Interface.MaxCacheSize || Slot.Height > Interface.MaxCacheSize) cacheEnabled = false; - } + } if (cacheEnabled) { if (IsDirty) { @@ -1915,9 +1911,10 @@ namespace Crow if (!IsEnabled) paintDisabled (ctx, rb); - } + } + LastPaintedSlot = Slot; - } + //} Painted.Raise (this, null); DbgLogger.EndEvent (DbgEvtType.GOPaint); diff --git a/Crow/src/Widgets/Window.cs b/Crow/src/Widgets/Window.cs index f7bd5144..07b575b0 100644 --- a/Crow/src/Widgets/Window.cs +++ b/Crow/src/Widgets/Window.cs @@ -154,7 +154,7 @@ namespace Crow /// <param name="YDelta">mouse delta on the Y axis</param> /// <param name="currentDirection">Current Direction of the operation, none for moving, other value for resizing in the given direction</param> protected void moveAndResize (int XDelta, int YDelta, Direction currentDirection = (Direction)0) { - lock (IFace.UpdateMutex) { + //lock (IFace.UpdateMutex) { int currentLeft = this.Left; int currentTop = this.Top; int currentWidth, currentHeight; @@ -223,7 +223,7 @@ namespace Crow this.Width = currentWidth + XDelta; break; } - } + //} } bool maySize => sizingHandle == null ? false : resizable & sizingHandle.IsHover; @@ -386,15 +386,15 @@ namespace Crow if (Parent is Interface) (Parent as Interface).DeleteWidget (this); else { - Widget p = Parent as Widget; - if (p is Group g) { - lock (IFace.UpdateMutex) { - RegisterClip (p.ScreenCoordinates (p.LastPaintedSlot)); - g.DeleteChild (this); - } - //(Parent as Group).RegisterForRedraw (); - } else if (Parent is Container c) - c.Child = null; + lock (IFace.UpdateMutex) { + Widget p = Parent as Widget; + if (p is Group g) { + RegisterClip (p.ScreenCoordinates (p.LastPaintedSlot)); + g.DeleteChild (this); + //(Parent as Group).RegisterForRedraw (); + } else if (Parent is Container c) + c.Child = null; + } } } diff --git a/Crow/src/Widgets/Wrapper.cs b/Crow/src/Widgets/Wrapper.cs index ead1f533..19243ba0 100644 --- a/Crow/src/Widgets/Wrapper.cs +++ b/Crow/src/Widgets/Wrapper.cs @@ -109,27 +109,27 @@ namespace Crow int largestChild = 0; childrenRWLock.EnterReadLock(); + try { + foreach (Widget c in Children) { + if (!c.IsVisible) + continue; + if (c.Height.IsRelativeToParent && + c.RegisteredLayoutings.HasFlag (LayoutingType.Height)) { + return -1; + } + if (dy + c.Slot.Height > ClientRectangle.Height) { + dy = 0; + tmp += largestChild + Spacing; + largestChild = c.Slot.Width; + } else if (largestChild < c.Slot.Width) + largestChild = c.Slot.Width; - foreach (Widget c in Children) { - if (!c.Visible) - continue; - if (c.Height.IsRelativeToParent && - c.RegisteredLayoutings.HasFlag (LayoutingType.Height)) { - childrenRWLock.ExitReadLock(); - return -1; + dy += c.Slot.Height + Spacing; } - if (dy + c.Slot.Height > ClientRectangle.Height) { - dy = 0; - tmp += largestChild + Spacing; - largestChild = c.Slot.Width; - } else if (largestChild < c.Slot.Width) - largestChild = c.Slot.Width; - - dy += c.Slot.Height + Spacing; + } finally { + childrenRWLock.ExitReadLock (); } - childrenRWLock.ExitReadLock (); - if (dy == 0) tmp -= Spacing; return tmp + largestChild + 2 * Margin; @@ -144,27 +144,27 @@ namespace Crow int tallestChild = 0; childrenRWLock.EnterReadLock(); + try { + foreach (Widget c in Children) { + if (!c.IsVisible) + continue; + if (c.Width.IsRelativeToParent && + c.RegisteredLayoutings.HasFlag (LayoutingType.Width)) { + return -1; + } + if (dx + c.Slot.Width > ClientRectangle.Width) { + dx = 0; + tmp += tallestChild + Spacing; + tallestChild = c.Slot.Height; + } else if (tallestChild < c.Slot.Height) + tallestChild = c.Slot.Height; - foreach (Widget c in Children) { - if (!c.Visible) - continue; - if (c.Width.IsRelativeToParent && - c.RegisteredLayoutings.HasFlag (LayoutingType.Width)) { - childrenRWLock.ExitReadLock(); - return -1; + dx += c.Slot.Width + Spacing; } - if (dx + c.Slot.Width > ClientRectangle.Width) { - dx = 0; - tmp += tallestChild + Spacing; - tallestChild = c.Slot.Height; - } else if (tallestChild < c.Slot.Height) - tallestChild = c.Slot.Height; - - dx += c.Slot.Width + Spacing; + } finally { + childrenRWLock.ExitReadLock(); } - childrenRWLock.ExitReadLock(); - if (dx == 0) tmp -= Spacing; return tmp + tallestChild + 2 * Margin; @@ -192,30 +192,35 @@ namespace Crow } public override void OnLayoutChanges (LayoutingType layoutType) { - switch (layoutType) { - case LayoutingType.Width: - foreach (Widget c in Children) { - if (c.Width.IsRelativeToParent) - c.RegisterForLayouting (LayoutingType.Width); - } - if (Height == Measure.Fit) - RegisterForLayouting (LayoutingType.Height); - RegisterForLayouting (LayoutingType.X); - break; - case LayoutingType.Height: - foreach (Widget c in Children) { - if (c.Height.IsRelativeToParent) - c.RegisterForLayouting (LayoutingType.Height); + childrenRWLock.EnterReadLock(); + try { + switch (layoutType) { + case LayoutingType.Width: + foreach (Widget c in Children) { + if (c.Width.IsRelativeToParent) + c.RegisterForLayouting (LayoutingType.Width); + } + if (Height == Measure.Fit) + RegisterForLayouting (LayoutingType.Height); + RegisterForLayouting (LayoutingType.X); + break; + case LayoutingType.Height: + foreach (Widget c in Children) { + if (c.Height.IsRelativeToParent) + c.RegisterForLayouting (LayoutingType.Height); + } + if (Width == Measure.Fit) + RegisterForLayouting (LayoutingType.Width); + RegisterForLayouting (LayoutingType.Y); + break; + default: + return; } - if (Width == Measure.Fit) - RegisterForLayouting (LayoutingType.Width); - RegisterForLayouting (LayoutingType.Y); - break; - default: - return; + RegisterForLayouting (LayoutingType.ArrangeChildren); + raiseLayoutChanged (layoutType); + } finally { + childrenRWLock.ExitReadLock(); } - RegisterForLayouting (LayoutingType.ArrangeChildren); - raiseLayoutChanged (layoutType); } #endregion } diff --git a/Samples/DebugLogAnalyzer/src/DbgEventWidget.cs b/Samples/DebugLogAnalyzer/src/DbgEventWidget.cs index 6af3f6df..b369d248 100644 --- a/Samples/DebugLogAnalyzer/src/DbgEventWidget.cs +++ b/Samples/DebugLogAnalyzer/src/DbgEventWidget.cs @@ -30,12 +30,15 @@ namespace Crow long ticksPerPixel; double pixelPerTick; + object dataMutex = new object(); + public DbgEvent Event { get => evt; set { if (evt == value) return; - evt = value; + lock (dataMutex) + evt = value; updatePixelPerTicks (); NotifyValueChangedAuto (evt); RegisterForRedraw (); @@ -46,6 +49,8 @@ namespace Crow private set { if (hoverEvt == value) return; + lock (dataMutex) + evt = value; hoverEvt = value; NotifyValueChangedAuto (hoverEvt); } @@ -83,24 +88,27 @@ namespace Crow protected override void onDraw (Context gr) { - if (Event == null) { - base.onDraw (gr); - return; - } + lock (dataMutex) { + + if (Event == null) { + base.onDraw (gr); + return; + } - gr.LineWidth = 1; - gr.SetDash (new double [] { 1.0, 3.0 }, 0); + gr.LineWidth = 1; + gr.SetDash (new double [] { 1.0, 3.0 }, 0); - Rectangle cb = ClientRectangle; + Rectangle cb = ClientRectangle; - if (Event.Duration == 0) { - gr.SetSource (Event.Color); - gr.Rectangle (cb); - gr.Fill (); - return; - } + if (Event.Duration == 0) { + gr.SetSource (Event.Color); + gr.Rectangle (cb); + gr.Fill (); + return; + } - drawEvent (gr, cb.Height, Event); + drawEvent (gr, cb.Height, Event); + } } void drawEvent (Context ctx, int h, DbgEvent dbge) { diff --git a/Samples/DebugLogAnalyzer/src/DbgLogViewer.cs b/Samples/DebugLogAnalyzer/src/DbgLogViewer.cs index d39cc62a..251090ef 100644 --- a/Samples/DebugLogAnalyzer/src/DbgLogViewer.cs +++ b/Samples/DebugLogAnalyzer/src/DbgLogViewer.cs @@ -481,7 +481,7 @@ namespace Crow if (lastTick >= 0 && hoverTick >= 0) ScrollX += lastTick - hoverTick; if (lastLine >= 0 && hoverLine >= 0) - ScrollY += lastLine - hoverLine; + ScrollY += lastLine - hoverLine; updateMouseLocalPos (e.Position); } else { HoverWidget = (hoverLine < 0 || hoverLine >= widgets.Count) ? null : widgets [hoverLine]; diff --git a/Samples/DebugLogAnalyzer/src/DebugInterface.cs b/Samples/DebugLogAnalyzer/src/DebugInterface.cs index 1653f163..64de2163 100644 --- a/Samples/DebugLogAnalyzer/src/DebugInterface.cs +++ b/Samples/DebugLogAnalyzer/src/DebugInterface.cs @@ -43,13 +43,28 @@ namespace Crow } catch (System.Exception ex) { - while (Monitor.IsEntered(LayoutMutex)) + while (Monitor.IsEntered(LayoutMutex)) { + Console.WriteLine ($"[DebugIFace] trying to exit LayoutMutex on error"); + Monitor.Exit (LayoutMutex); + } + while (Monitor.IsEntered(UpdateMutex)) { + Console.WriteLine ($"[DebugIFace] trying to exit UpdateMutex on error"); + Monitor.Exit (UpdateMutex); + } + while (Monitor.IsEntered(ClippingMutex)) { + Console.WriteLine ($"[DebugIFace] trying to exit ClippingMutex on error"); + Monitor.Exit (ClippingMutex); + } + + + /*while (Monitor.IsEntered(LayoutMutex)) Monitor.Exit (LayoutMutex); while (Monitor.IsEntered(UpdateMutex)) Monitor.Exit (UpdateMutex); while (Monitor.IsEntered(ClippingMutex)) - Monitor.Exit (ClippingMutex); - delSetCurrentException (ex); + Monitor.Exit (ClippingMutex);*/ + delSetCurrentException (ex); + Console.WriteLine ($"[DbgIFace] {ex}"); ClearInterface(); Thread.Sleep(1000); } diff --git a/Samples/DebugLogAnalyzer/src/Program.cs b/Samples/DebugLogAnalyzer/src/Program.cs index 8cee874a..13e0234d 100644 --- a/Samples/DebugLogAnalyzer/src/Program.cs +++ b/Samples/DebugLogAnalyzer/src/Program.cs @@ -21,8 +21,7 @@ namespace DebugLogAnalyzer static void Main (string [] args) { - DbgLogger.IncludeEvents = DbgEvtType.None; - DbgLogger.DiscardEvents = DbgEvtType.All; + initDebugLog (); using (Program app = new Program ()) { CurrentProgramInstance = app; @@ -195,15 +194,6 @@ namespace DebugLogAnalyzer } public List<DbgWidgetEvent> CurWidgetRootEvents => curWidget == null? new List<DbgWidgetEvent>() : curWidget.RootEvents; - public bool DebugLogToFile { - get => Configuration.Global.Get<bool> (nameof(DebugLogToFile)); - set { - if (DbgLogger.ConsoleOutput != value) - return; - Configuration.Global.Set (nameof(DebugLogToFile), value); - NotifyValueChanged(DebugLogToFile); - } - } /*public string DebugLogFilePath { get => Configuration.Global.Get<string> (nameof (DebugLogFilePath)); set { @@ -216,8 +206,8 @@ namespace DebugLogAnalyzer public bool DebugLogOnStartup { get => Configuration.Global.Get<bool> (nameof(DebugLogOnStartup)); set { - if (DbgLogger.ConsoleOutput != value) - return; + if (DebugLogOnStartup == value) + return; Configuration.Global.Set (nameof(DebugLogOnStartup), value); NotifyValueChanged(DebugLogOnStartup); } diff --git a/Samples/DebugLogAnalyzer/ui/DebugLog.crow b/Samples/DebugLogAnalyzer/ui/DebugLog.crow index 2b5ab978..a4e947af 100644 --- a/Samples/DebugLogAnalyzer/ui/DebugLog.crow +++ b/Samples/DebugLogAnalyzer/ui/DebugLog.crow @@ -31,7 +31,7 @@ <Label Style="smallLabValue" Tooltip="VisibleTicks" Text="{../../dbv.VisibleTicks}"/> </HorizontalStack> </VerticalStack> - <!--<VerticalStack Name="AllEvents" Width="Stretched" IsVisible="false"> + <VerticalStack Name="AllEvents" Width="Stretched" IsVisible="false"> <TreeView Height="Stretched" Name="dbgTV" Data="{Events}" SelectedItem="{²CurrentEvent}" Background="DarkGrey" ItemTemplate="#Dbg.DbgEventTreeItems.itemp"/> <ListBox Data="{CurWidgetEvents}" Height="100" SelectedItem="{²CurrentEvent}"> @@ -50,7 +50,7 @@ <VerticalStack Name="CurWidgetEvents" Width="Stretched" IsVisible="false"> <TreeView Height="Stretched" Data="{CurrentWidgetEvents}" Background="DarkGrey" ItemTemplate="#Dbg.DbgEventTreeItems.itemp"/> - </VerticalStack>--> + </VerticalStack> </TabView> <Splitter/> <HorizontalStack Height="30%"> diff --git a/Samples/ShowCase/ShowCase.cs b/Samples/ShowCase/ShowCase.cs index 95d15a85..fdbe6aa3 100644 --- a/Samples/ShowCase/ShowCase.cs +++ b/Samples/ShowCase/ShowCase.cs @@ -21,9 +21,7 @@ namespace ShowCase { static void Main () { - DbgLogger.IncludeEvents = DbgEvtType.Layouting; - //DbgLogger.DiscardEvents = DbgEvtType.All; - //DbgLogger.ConsoleOutput = !Configuration.Global.Get<bool> (nameof (DebugLogToFile)); + initDebugLog (); Environment.SetEnvironmentVariable ("FONTCONFIG_PATH", @"C:\Users\Jean-Philippe\source\vcpkg\installed\x64-windows\tools\fontconfig\fonts"); @@ -108,17 +106,6 @@ namespace ShowCase reloadChrono.Reset (); } - - public bool DebugLogToFile { - get => !DbgLogger.ConsoleOutput; - set { - if (DbgLogger.ConsoleOutput != value) - return; - DbgLogger.ConsoleOutput = !value; - Configuration.Global.Set (nameof(DebugLogToFile), DebugLogToFile); - NotifyValueChanged(DebugLogToFile); - } - } public string DebugLogFilePath { get => Configuration.Global.Get<string> (nameof (DebugLogFilePath)); set { diff --git a/Samples/common/src/SampleBaseForEditor.cs b/Samples/common/src/SampleBaseForEditor.cs index 4af718a2..54ad8777 100644 --- a/Samples/common/src/SampleBaseForEditor.cs +++ b/Samples/common/src/SampleBaseForEditor.cs @@ -98,6 +98,23 @@ namespace Samples NotifyValueChanged(debugLogRecording); } } + public bool DebugLogToFile { + get => Configuration.Global.Get<bool> (nameof(DebugLogToFile)); + set { + if (DebugLogToFile != value) + return; + Configuration.Global.Set (nameof(DebugLogToFile), value); + NotifyValueChanged(DebugLogToFile); + DbgLogger.ConsoleOutput = !value; + } + } + protected static void initDebugLog () { + DbgLogger.IncludeEvents = DbgEvtType.None; + DbgLogger.DiscardEvents = DbgEvtType.All; + //DbgLogger.DiscardEvents = DbgEvtType.All; + DbgLogger.ConsoleOutput = !Configuration.Global.Get<bool> (nameof (DebugLogToFile)); + } + public new bool IsDirty => source != origSource; diff --git a/Samples/common/ui/Interfaces/Divers/0.crow b/Samples/common/ui/Interfaces/Divers/0.crow index f84ad20a..263edfc7 100644 --- a/Samples/common/ui/Interfaces/Divers/0.crow +++ b/Samples/common/ui/Interfaces/Divers/0.crow @@ -2,26 +2,21 @@ <Window Caption="Showcase" Height="90%" Width="90%" Background="DarkGrey"> <HorizontalStack> <VerticalStack Width="30%" Margin="5"> - <GroupBox Caption="Performance" Height="Fit"> - <VerticalStack DataSource="{updateMeasure}" Width="90%" Height="Fit" Spacing="2"> + <ListBox Data="{PerfMeasures}" Height="Fit"> + <Template> + <GroupBox Caption="Performance"> + <VerticalStack Name="ItemsContainer" Width="90%" Spacing="2"/> + </GroupBox> + </Template> + <ItemTemplate> <HorizontalStack Style="HStackMeasure"> - <Label Text="Cur:" Style="FpsLabel"/> - <Label Text="{current}" Style="FpsDisp"/> + <Label Text="{Name}" Style="FpsLabel" Width="80"/> + <Label Text="{current}" Style="FpsDisp" Width="60" TextAlignment="Right" Margin="2"/> + <Label Text="{minimum}" Style="FpsDisp" Width="60" TextAlignment="Right" Margin="2"/> + <Label Text="{maximum}" Style="FpsDisp" Width="60" TextAlignment="Right" Margin="2"/> </HorizontalStack> - <HorizontalStack Style="HStackMeasure"> - <Label Text="Min:" Style="FpsLabel"/> - <Label Text="{minimum}" Style="FpsDisp"/> - </HorizontalStack> - <HorizontalStack Style="HStackMeasure"> - <Label Text="Mean:" Style="FpsLabel"/> - <Label Text="{mean}" Style="FpsDisp"/> - </HorizontalStack> - <HorizontalStack Style="HStackMeasure"> - <Label Text="Max:" Style="FpsLabel"/> - <Label Text="{maximum}" Style="FpsDisp"/> - </HorizontalStack> - </VerticalStack> - </GroupBox> + </ItemTemplate> + </ListBox> <Label Width="Stretched" Margin="3" Background="DimGrey" /> <TextBox Text="TextBox" Multiline="true" Margin="3" /> <HorizontalStack Height="Fit" Margin="5" Background="DimGrey" CornerRadius="10"> @@ -75,7 +70,7 @@ <Splitter /> <VerticalStack Width="Stretched" Margin="5" Spacing="5"> <Expandable> - <Image Path="#Crow.Icons.crow.svg" /> + <Image Path="#Crow.Icons.crow.svg" Background="White" Height="100" Width="Stretched" Margin="20"/> </Expandable> <Popper > <Image Path="#Crow.Icons.crow.svg" Background="White" Height="100" Width="100" Margin="20" /> diff --git a/Samples/common/ui/Interfaces/Divers/02.crow b/Samples/common/ui/Interfaces/Divers/02.crow new file mode 100644 index 00000000..978687e2 --- /dev/null +++ b/Samples/common/ui/Interfaces/Divers/02.crow @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ListBox Data="{PerfMeasures}"> + <Template> + <GroupBox Caption="Performance" Height="Fit"> + <VerticalStack Name="ItemsContainer" Width="90%" Height="Fit" Spacing="2"/> + </GroupBox> + </Template> + <ItemTemplate> + <HorizontalStack Style="HStackMeasure"> + <Label Text="{Name}" Style="FpsLabel" Width="100"/> + <Label Text="{current}" Style="FpsDisp" Width="80" TextAlignment="Right" Margin="2"/> + </HorizontalStack> + </ItemTemplate> +</ListBox>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Divers/testBind0.crow b/Samples/common/ui/Interfaces/Divers/testBind0.crow index 5d8f226c..9fecb30f 100644 --- a/Samples/common/ui/Interfaces/Divers/testBind0.crow +++ b/Samples/common/ui/Interfaces/Divers/testBind0.crow @@ -1,5 +1,5 @@ <?xml version="1.0"?> <VerticalStack Fit="true"> - <TextBox Text="{Datas}" Width="100" /> - <Button Caption="Set Text to Null" MouseClick="onSetDataToNull"/> + <TextBox Text="{Datas}" Width="100" Name="tb"/> + <Button Caption="Set Text to Null" MouseClick="{../tb.Text=''}"/> </VerticalStack>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Divers/testVisibility.crow b/Samples/common/ui/Interfaces/Divers/testVisibility.crow index 581bab06..af33613a 100644 --- a/Samples/common/ui/Interfaces/Divers/testVisibility.crow +++ b/Samples/common/ui/Interfaces/Divers/testVisibility.crow @@ -1,8 +1,8 @@ <?xml version="1.0"?> <Container Margin="20" Background="Red" > - <!--<Container Margin="20" Background="Green" MouseDown="{../go1.Visible=True}" > - <Widget Name="go1" Margin="20" Background="DimGrey" Visible="false" MouseDown="{Visible=false}" + <Container Margin="20" Background="Green" MouseDown="{../go1.IsVisible='True'}" > + <Widget Name="go1" Margin="20" Background="DimGrey" Visible="false" MouseDown="{IsVisible='false'}" MouseEnter="{Background=Blue}" MouseLeave="{Background=DimGrey}"/> - </Container>--> + </Container> </Container> diff --git a/Samples/common/ui/Interfaces/Divers/welcome.crow b/Samples/common/ui/Interfaces/Divers/welcome.crow index fa6da1e6..9c7e942c 100644 --- a/Samples/common/ui/Interfaces/Divers/welcome.crow +++ b/Samples/common/ui/Interfaces/Divers/welcome.crow @@ -1,21 +1,19 @@ <?xml version="1.0"?> -<Border BorderStyle="Sunken" Fit="true" Background="0.7,0.7,0.7,0.5" CornerRadius="10"> - <VerticalStack Margin="20"> - <Image Path="#Crow.Icons.crow.svg"/> +<Border BorderStyle="Sunken" Fit="true" Background="0.8,0.8,0.9,0.5" CornerRadius="30"> + <VerticalStack Margin="20" Spacing="10"> + <Image Path="#Crow.Icons.crow.svg" Width="64" Height="64" Background="WhiteSmoke" CornerRadius="5" Margin="5"/> <!-- <Label Font="Times bold, 60" Text="C.R.O.W"/>--> - <HorizontalStack Fit="true" DataSource="{CrowVersion}" Spacing="0"> - <Label Foreground="Black" Font="mono, 12" Text="version: "/> - <Label Foreground="Black" Font="mono, 12" Text="{Major}"/> + <HorizontalStack Fit="true" DataSource="{CrowVersion}" Spacing="0" Background="Grey" Margin="10" CornerRadius="15"> + <Label Foreground="Jet" Font="mono, 12" Text="version: "/> + <Label Foreground="Black" Font="mono, 16" Text="{Major}"/> <Label Foreground="Black" Font="mono, 12" Text="."/> - <Label Foreground="Black" Font="mono, 12" Text="{Minor}"/> + <Label Foreground="Black" Font="mono, 16" Text="{Minor}"/> <Label Foreground="Black" Font="mono, 12" Text="."/> - <Label Foreground="DimGrey" Font="mono, 12" Text="{Build}"/> + <Label Foreground="DarkBlue" Font="mono, 14" Text="{Build}" VerticalAlignment="Bottom"/> </HorizontalStack> - <Widget Height="30"/> <Label Font="20" Text="Press <F2> and <F3> to cycle into the examples"/> <Label Font="20" Text="Those are basic tests used to validate changes,"/> - <Widget Height="30"/> - <Label Foreground="DimGrey" Font="20" Text="<F5> => File dialog example"/> - <Label Foreground="DimGrey" Font="20" Text="<F6> => Window example"/> + <Label Foreground="Onyx" Font="20" Text="<F5> => File dialog example"/> + <Label Foreground="Onyx" Font="20" Text="<F6> => Window example"/> </VerticalStack> </Border>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Experimental/colorTable.crow b/Samples/common/ui/Interfaces/Experimental/colorTable.crow index 29790261..e654abed 100644 --- a/Samples/common/ui/Interfaces/Experimental/colorTable.crow +++ b/Samples/common/ui/Interfaces/Experimental/colorTable.crow @@ -1,13 +1,15 @@ <ListBox Data="{TestList}" > <Template> <Scroller> - <Table Name="ItemsContainer" Columns="name,Fit;color,100" Height="Fit" Width="Stretched" VerticalAlignment="Top"/> + <Table Name="ItemsContainer" Columns="name,Fit;color,100" Height="Fit" Width="Fit" VerticalAlignment="Top"/> </Scroller> </Template> <ItemTemplate> <TableRow> <Label Text="{}" Margin="5" /> - <Widget Background="{}" Width="50" Height="10"/> + <Container Height="Stretched" Margin="5"> + <Widget Background="{}" /> + </Container> </TableRow> </ItemTemplate> diff --git a/Samples/common/ui/Interfaces/Experimental/table2.crow b/Samples/common/ui/Interfaces/Experimental/table2.crow deleted file mode 100644 index 4aa3eebb..00000000 --- a/Samples/common/ui/Interfaces/Experimental/table2.crow +++ /dev/null @@ -1,20 +0,0 @@ -<List Data="{TestList}"> - <Table Foreground="White" Columns="test,Fit;test,Fit" Width="Fit" Height="Fit" - Spacing="1" ColumnSpacing="1" - VerticalLineWidth="1" Margin="0" RowsMargin="0"> - <TableRow - MouseEnter="{Background=RoyalBlue}" - MouseLeave="{Background=Transparent}"> - <Label Text="col1qsf" Margin="5" /> - <Label Text="col1qsf" Margin="5" /> - <Label Text="col1qsf" Margin="5" /> - </TableRow> - <TableRow - MouseEnter="{Background=RoyalBlue}" - MouseLeave="{Background=Transparent}"> - <Label Text="col1qsf" Margin="5"/> - <Label Text="col1qsfsdqfdqsfdqsfdqsf" Margin="5"/> - <Label Text="col1qsfdsqfdqsf" Margin="5"/> - </TableRow> - </Table> -</List>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Experimental/table3.crow b/Samples/common/ui/Interfaces/Experimental/table3.crow deleted file mode 100644 index 0a9e0b52..00000000 --- a/Samples/common/ui/Interfaces/Experimental/table3.crow +++ /dev/null @@ -1,9 +0,0 @@ -<Table Foreground="White" Columns="test,Fit;test,Fit" Background="White" Width="Fit" Height="Fit" Margin="100" Spacing="10" > - <TableRow Height="Fit" Spacing="3" Margin="10" - MouseEnter="{Background=RoyalBlue}" - MouseLeave="{Background=Transparent}"> - <Label Text="col1qsf" Margin="5" Background="0.3,0.3,0.3,0.8"/> - <Label Text="col1qsf" Margin="5" Background="0.3,0.3,0.3,0.8"/> - <Label Text="col1qsf" Margin="5" Background="0.3,0.3,0.3,0.8"/> - </TableRow> -</Table>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/TemplatedContainer/testTabView.crow b/Samples/common/ui/Interfaces/TemplatedContainer/testTabView.crow index f54a7182..3def987f 100644 --- a/Samples/common/ui/Interfaces/TemplatedContainer/testTabView.crow +++ b/Samples/common/ui/Interfaces/TemplatedContainer/testTabView.crow @@ -2,23 +2,23 @@ <VerticalStack > <HorizontalStack Height="Fit"> <Label Text="Selected Tab:"/> - <Label Name="lab" /> + <Label Name="lab" Text="{../../tabview1.SelectedItem}" /> </HorizontalStack> - <TabView Name="tabview1" Background="DimGrey" Orientation="Horizontal" - SelectedItemChanged="{../lab.Background='Blue'}"> - <VerticalStack Name="tab #1" Margin="20"> + <TabView Name="tabview1" Orientation="Horizontal" + SelectedItemChanged="{../../lab.Background=Blue}"> + <VerticalStack Name="tab #1" Margin="20" Background="Onyx"> <CheckBox/> <CheckBox/> <CheckBox/> <CheckBox/> </VerticalStack> - <VerticalStack Name="tab #2" Margin="20"> + <VerticalStack Name="tab #2" Margin="20" Background="Onyx"> <RadioButton/> <RadioButton/> <RadioButton/> <RadioButton/> </VerticalStack> - <VerticalStack Name="tab #3" Margin="20"> + <VerticalStack Name="tab #3" Margin="20" Background="Onyx"> <TextBox/> <TextBox/> <TextBox/> diff --git a/Samples/common/ui/Interfaces/TemplatedContainer/testTabView2.crow b/Samples/common/ui/Interfaces/TemplatedContainer/testTabView2.crow deleted file mode 100644 index 8e208aea..00000000 --- a/Samples/common/ui/Interfaces/TemplatedContainer/testTabView2.crow +++ /dev/null @@ -1,65 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<HorizontalStack Height="90%" Width="99%" Spacing="50"> - <VerticalStack Width="40%"> - <HorizontalStack Height="Fit"> - <Label Text="Selected Tab:"/> - <Label Text="{../../tabview1.SelectedTab}"/> - </HorizontalStack> - <TabView Name="tabview1" Background="DimGrey" Orientation="Horizontal" Margin="5" > - <TabItem Name="TabItem1" Caption="tab-1.1" Background="DimGrey"> - <VerticalStack Margin="20"> - <CheckBox/> - <CheckBox/> - <CheckBox/> - <CheckBox/> - </VerticalStack> - </TabItem> - <TabItem Name="TabItem2" Caption="tab-1.2" Background="DimGrey"> - <VerticalStack Height="Fit" Margin="10"> - <RadioButton Fit="true"/> - <RadioButton/> - <RadioButton/> - <RadioButton/> - </VerticalStack> - </TabItem> - <TabItem Name="TabItem3" Background="DimGrey" Caption="tab-1.3"> - <Container Margin="5" CornerRadius="2" > - <TextBox Margin="5" Multiline="true" TextAlignment="Left"/> - </Container> - </TabItem> - </TabView> - <Button Background="vgradient|0:DimGrey|1:Black" HorizontalAlignment="Right" - Caption="Add new tab" Width="Fit" Height="30" MouseDown="onAddTabButClick"/> - </VerticalStack> - <VerticalStack Width="40%"> - <HorizontalStack Height="Fit"> - <Label Text="Selected Tab:"/> - <Label Text="{../../tabview2.SelectedTab}"/> - </HorizontalStack> - <TabView Name="tabview2" Background="DimGrey" Orientation="Horizontal" > - <TabItem Name="TabItem1" Caption="tab-2.1" Background="DimGrey"> - <VerticalStack Margin="20"> - <CheckBox/> - <CheckBox/> - <CheckBox/> - <CheckBox/> - </VerticalStack> - </TabItem> - <TabItem Name="TabItem2" Caption="tab-2.2" Background="DimGrey"> - <VerticalStack Height="Fit" Margin="10"> - <RadioButton Fit="true"/> - <RadioButton/> - <RadioButton/> - <RadioButton/> - </VerticalStack> - </TabItem> - <TabItem Name="TabItem3" Background="DimGrey" Caption="tab-2.3"> - <Container Margin="5" CornerRadius="2" > - <TextBox Margin="5" Multiline="true" TextAlignment="Left"/> - </Container> - </TabItem> - </TabView> - <Button Background="vgradient|0:DimGrey|1:Black" HorizontalAlignment="Right" - Caption="Add new tab" Width="Fit" Height="30" MouseDown="onAddTabButClick2"/> - </VerticalStack> -</HorizontalStack> |