--- /dev/null
+<?xml version="1.0"?>
+<Label RootDataLevel="true" Style="TableHeaderLabel" Text="{Caption}" Width="{Width}"/>
\ No newline at end of file
<?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}">
#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);
/// <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;
/// <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;
}
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))
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
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;
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 ();
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);
//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);
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);
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++) {
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;
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++) {
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;
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);
}
}
}
--- /dev/null
+// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+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);
+ }
+ }
+}
--- /dev/null
+// 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);
+ }*/
+ }
+}
string caption;
Measure width = Measure.Fit;
public int ComputedWidth;
- public Widget LargestWidget;
+ public Widget LargestChild;
public string Caption {
get => caption;
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)
+ 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 ();
+
+ 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 ();
+ }
+ }
+ 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()
{
- //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 as the same total width.
- public override void ComputeChildrenPositions () {
- int d = 0;
- childrenRWLock.EnterReadLock();
- foreach (Widget c in Children) {
- if (!c.Visible)
+ base.ClearChildren();
+ createHeaderRow ();
+ }
+
+ void searchLargestChildInColumn (int cIdx)
+ {
+ DbgLogger.StartEvent (DbgEvtType.GOSearchLargestChild, this);
+
+ 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;
- c.Slot.Y = d;
- d += c.Slot.Height + Spacing;
+ int cw = row.Children [cIdx]. measureRawSize (LayoutingType.Width);
+ if (cw > largestWidth) {
+ largestWidth = cw;
+ c.LargestChild = row.Children [cIdx];
+ }
}
- childrenRWLock.ExitReadLock();
- IsDirty = true;
+ 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);
}
- public override bool UpdateLayout(LayoutingType layoutType)
+ int splitIndex = -1;
+ const int minColumnSize = 10;
+ public override void onMouseMove(object sender, MouseMoveEventArgs e)
{
- RegisteredLayoutings &= (~layoutType);
-
- 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;
- }
- }
- 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);
- }
+
+ 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);
- }*/
- }
+ }
+
+ }
}
--- /dev/null
+// 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);
+ }
+ }
+}
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; }
}
}
#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);
+ #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;
+ 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);
-
- 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;
- }
+ child.LayoutChanged -= OnChildLayoutChanges;
+ //check if HoverWidget is removed from Tree
+ if (IFace.HoverWidget != null) {
+ if (this.Contains (IFace.HoverWidget))
+ IFace.HoverWidget = null;
}
-
- return base.UpdateLayout(layoutType);
+
+ 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);
+
}
- /*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 ();
}
- 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;
+ 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 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;
-
- 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;
+ childrenRWLock.ExitReadLock ();
+ }
+ public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
+ {
+ DbgLogger.StartEvent(DbgEvtType.GOOnChildLayoutChange, this);
+
+ 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;
}
-
- 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;
+ DbgLogger.EndEvent(DbgEvtType.GOOnChildLayoutChange);
+ }
+ 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];
}
}
- base.onMouseMove(sender, e);
+ if (tallestChild == null && !forceMeasure)
+ searchTallestChild (true);
+
+ childrenRWLock.ExitReadLock ();
+
+ DbgLogger.EndEvent (DbgEvtType.GOSearchTallestChild);
+ }
+ void resetChildrenMaxSize(){
+ tallestChild = null;
+ contentSize = 0;
}
}
}
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);
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.
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);
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);
}
/// of the widget </summary>
public virtual void Paint (Context ctx)
{
- if (!IsVisible)
- return;
+ /*if (!IsVisible)
+ return;*/
DbgLogger.StartEvent (DbgEvtType.GOPaint, this);
/// 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) {
}
LastSlots = default;
LastPaintedSlot = default;*/
-
+ //Slot = LastSlots = default;
}
}
}