<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- <TargetFrameworks>netstandard2.0</TargetFrameworks>-->
- <TargetFrameworks>netstandard2.1</TargetFrameworks>
+ <TargetFramework>netstandard2.1</TargetFramework>
<AssemblyVersion>$(CrowVersion)</AssemblyVersion>
<PackageVersion>$(CrowPackageVersion)</PackageVersion>
/// - global static constants and variables of CROW
/// - Keyboard and Mouse logic
/// - the resulting bitmap of the interface
- ///
+ ///
/// the master branch and the nuget package includes an OpenTK renderer which allows
/// the creation of multiple threaded interfaces.
- ///
+ ///
/// If you intend to create another renderer (GDK, vulkan, etc) the minimal step is to
/// put an interface instance as member of your root object and call (optionally in another thread) the update function
/// at regular interval. Then you have to call
/// mouse, keyboard and resize functions of the interface when those events occurs in the host app.
- ///
+ ///
/// The resulting surface (a byte array in the OpenTK renderer) is made available and protected with the
/// RenderMutex of the interface.
/// </remarks>
#endregion
internal static List<Assembly> crowAssemblies = new List<Assembly> ();
+ /// <summary>
+ /// Add Assembly that may contains CROW ui stuf like widgets or iml.
+ /// Styling fond in that assembly are automatically loaded on addition;
+ /// This assembly will be searched for embedded ressource resolution, extension methods, and custom widgets.
+ /// For those assembly to be added by simple name, see 'CrowAssemblyNames'.
+ /// </summary>
+ /// <param name="a">The assembly to add.</param>
public void AddCrowAssembly (Assembly a) {
lock (UpdateMutex) {
if (crowAssemblies.Contains (a))
loadStylingFromAssembly (a);
}
}
+ /// <summary>
+ /// Remove Assembly from the CrowAssembly list. See 'AddCrowAssembly' for details.
+ /// </summary>
+ /// <param name="a"></param>
public void RemoveCrowAssembly (Assembly a) {
lock (UpdateMutex) {
if (!crowAssemblies.Contains (a))
FontRenderingOptions.HintMetrics = HintMetrics.On;
FontRenderingOptions.HintStyle = HintStyle.Full;
FontRenderingOptions.SubpixelOrder = SubpixelOrder.Default;
-
-
}
+ /// <summary>
+ /// Each time this array is set, the resolved Assemblies will be
+ /// added to the CrowAssemblies list, see 'AddCrowAssembly' for details.
+ /// </summary>
+ /// <value></value>
public static string [] CrowAssemblyNames {
set {
if (value == null)
crowAssemblies.Add (a);
} catch {
- }
+ }
}*/
foreach (string assemblyName in crowAssemblyNames) {
try {
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine ($"Unable to preload CrowAssembly: {assemblyName}: {ex}");
Console.ResetColor();
- }
+ }
}
}
-
+ /// <summary>
+ /// Create a new Crow Interface by providing an existing valid GLFW window handle.
+ /// UI thread will not be started, and the main surface will not be initialized.
+ /// This is used to give crow support to existing glfw application by providing
+ /// a custom suface creation, and a custom update thread.
+ /// </summary>
+ /// <param name="width">the width of the window</param>
+ /// <param name="height">the height of the window</param>
+ /// <param name="glfwWindowHandle">A valid GLFW window handle</param>
+ /// <returns></returns>
public Interface (int width, int height, IntPtr glfwWindowHandle) : this (width, height, false, false)
{
hWin = glfwWindowHandle;
PerformanceMeasure.InitMeasures ();
}
-#if VKVG
+#if VKVG
public const bool HaveVkvgBackend = true;
#else
public const bool HaveVkvgBackend = false;
#endif
+ /// <summary>
+ /// Create a standard Crow interface
+ /// </summary>
+ /// <param name="width">the width of the native window</param>
+ /// <param name="height">the height of the native window</param>
+ /// <param name="startUIThread">If 'yes' start the ui update (InterfaceThread method) in a dedicated thread</param>
+ /// <param name="createSurface">If 'yes', create the main rendering surface on the native window</param>
public Interface (int width = 800, int height = 600, bool startUIThread = true, bool createSurface = true)
{
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
hWin = Glfw3.CreateWindow (clientRectangle.Width, clientRectangle.Height, "win name", MonitorHandle.Zero, IntPtr.Zero);
if (hWin == IntPtr.Zero)
throw new Exception ("[GLFW3] Unable to create vulkan Window");
- ownWindow = true;
+ ownWindow = true;
registerGlfwCallbacks ();
#else
surf = new ImageSurface (Format.Argb32, r.Width, r.Height);
#endif
- }
+ }
public Surface CreateSurface (ref Rectangle r) {
#if (VKVG)
return new Surface (vkvgDevice, r.Width, r.Height);
return new Surface (vkvgDevice, width, height);
#else
return surf.CreateSimilar (Content.ColorAlpha, width, height);
-#endif
+#endif
}
public Surface CreateSurface (IntPtr existingSurfaceHandle) {
#if (VKVG)
return new Surface (vkvgDevice, existingSurfaceHandle);
#else
- return Surface.Lookup (existingSurfaceHandle, false);
+ return Surface.Lookup (existingSurfaceHandle, false);
#endif
}
public Surface CreateSurfaceForData (IntPtr data, int width, int height) {
Glfw.Image icon = new Glfw.Image ((uint)stbi.Width, (uint)stbi.Height, image);
Glfw3.SetWindowIcon (hWin, 1, ref icon);
icon.Dispose();
-
+
#else
using (StbImage stbi = new StbImage (stream)) {
byte[] image = new byte [stbi.Size];
};
#endregion
-
- public string WindowTitle {
+
+ public string WindowTitle {
set => Glfw3.SetWindowTitle (hWin, value);
}
disposeContextMenus ();
initDictionaries ();
loadStyling ();
- loadThemeFiles ();
+ loadThemeFiles ();
initContextMenus ();
- }
+ }
/// <summary>
/// call Init() then enter the running loop performing ProcessEvents until running==false.
/// </summary>
Glfw3.PollEvents ();
UpdateFrame ();
}
-
+
Terminate ();
}
public virtual void Terminate () {}
/// <summary>Sync mutex between host and Crow for rendering operations (bmp, dirtyBmp,...)</summary>
public object RenderMutex = new object();
/// <summary>Global lock of the update cycle</summary>
- public object UpdateMutex = new object();
+ public object UpdateMutex = new object();
/// <summary>Global lock of the clipping queue</summary>
public object ClippingMutex = new object();
//TODO:share resource instances
/// <summary>each IML and fragments (such as inline Templates) are compiled as a Dynamic Method stored here
/// on the first instance creation of a IML item.
/// </summary>
- public Dictionary<String, Instantiator> Instantiators;
+ public Dictionary<String, Instantiator> Instantiators;
/// <summary>
/// default templates dic by metadata token
/// </summary>
lock (UpdateMutex) {
if (DragImage == null)
return;
- clipping.UnionRectangle (lastDragImageBounds);
+ clipping.UnionRectangle (lastDragImageBounds);
DragImage.Dispose();
DragImage = null;
DragImageBounds = lastDragImageBounds = default;
loadThemeStyle ();
loadStylingFromAssembly (Assembly.GetEntryAssembly ());
foreach (Assembly a in crowAssemblies)
- loadStylingFromAssembly (a);
+ loadStylingFromAssembly (a);
loadStylingFromAssembly (Assembly.GetExecutingAssembly ());
}
/// <summary> Search for .style resources in assembly </summary>
foreach (string s in assembly
.GetManifestResourceNames ()
.Where (r => r.EndsWith (".style", StringComparison.OrdinalIgnoreCase))) {
- using (StyleReader sr = new StyleReader (assembly.GetManifestResourceStream (s)))
+ using (StyleReader sr = new StyleReader (assembly.GetManifestResourceStream (s)))
sr.Parse (StylingConstants, Styling, s);
}
}
Styling = new Dictionary<string, Style> (initCapacity);
DefaultValuesLoader = new Dictionary<string, LoaderInvoker> (initCapacity);
Instantiators = new Dictionary<string, Instantiator> (initCapacity);
- DefaultTemplates = new Dictionary<string, Instantiator> (initCapacity);
+ DefaultTemplates = new Dictionary<string, Instantiator> (initCapacity);
ItemTemplates = new Dictionary<string, ItemTemplate> (initCapacity);
}
void loadThemeFiles () {
if (tryGetResource (AppDomain.CurrentDomain.GetAssemblies ()
.FirstOrDefault (aa => aa.GetName ().Name == $"{assemblyNames[0]}.{assemblyNames[1]}"), resId, out stream))
return stream;
- foreach (Assembly ca in crowAssemblies)
+ foreach (Assembly ca in crowAssemblies)
if (tryGetResource (ca, resId, out stream))
return stream;
throw new Exception ("Resource not found: " + path);
- }
+ }
if (!File.Exists (path))
throw new FileNotFoundException ($"File not found: {path}", path);
return new FileStream (path, FileMode.Open, FileAccess.Read);
/// </summary>
/// <returns>return the new instantiator</returns>
/// <param name="imlFragment">a valid IML string</param>
- public Instantiator CreateITorFromIMLFragment (string imlFragment) {
+ public Instantiator CreateITorFromIMLFragment (string imlFragment) {
return Instantiator.CreateFromImlFragment (this, imlFragment);
}
/// <summary>
}
_focusedWidget = value;
- NotifyValueChanged ("FocusedWidget", _focusedWidget);
+ NotifyValueChanged ("FocusedWidget", _focusedWidget);
if (_focusedWidget != null)
_focusedWidget.HasFocus = true;
}
/// Once in that queue, that means that the layouting of obj and childs have succeed,
/// the next step when dequeued will be clipping registration</summary>
public void EnqueueForRepaint(Widget g)
- {
+ {
lock (ClippingMutex) {
if (g.IsQueueForClipping)
return;
if (!Monitor.TryEnter (UpdateMutex))
return;
-
+
DbgLogger.StartEvent (DbgEvtType.Update);
PerformanceMeasure.Begin (PerformanceMeasure.Kind.Update);
if (!clipping.IsEmpty) {
if (ctx == null) {
- using (ctx = new Context (surf))
+ using (ctx = new Context (surf))
processDrawing (ctx);
}else
processDrawing (ctx);
if (!vkCtx.render ())
ProcessResize (new Rectangle (0,0,(int)vkCtx.width, (int)vkCtx.height));
}
-#endif
-
+#endif
+
} finally {
PerformanceMeasure.End (PerformanceMeasure.Kind.Update);
}
#if VKVG
void resizeVulkanContext () {
-
+
}
ctx.ClipPreserve ();
ctx.Operator = Operator.Clear;
- ctx.Fill ();
- ctx.Operator = Operator.Over;
+ ctx.Fill ();
+ ctx.Operator = Operator.Over;
}
bool solidBackground = false;
public bool SolidBackground {
/// repainted. If it contains also clip rectangles, its cache will be update, or if not cached a full redraw will take place</summary>
protected virtual void processDrawing(Context ctx){
DbgLogger.StartEvent (DbgEvtType.ProcessDrawing);
-
- PerformanceMeasure.Begin (PerformanceMeasure.Kind.Drawing);
-#if VKVG
+ PerformanceMeasure.Begin (PerformanceMeasure.Kind.Drawing);
+
+#if VKVG
clear (ctx);
#else
ctx.PushGroup ();
if (SolidBackground)
clear (ctx);
#endif
-
+
for (int i = GraphicTree.Count -1; i >= 0 ; i--){
Widget p = GraphicTree[i];
if (!p.IsVisible)
ctx.Restore ();
}
-
+
if (lastDragImageBounds != DragImageBounds) {
DirtyRect += lastDragImageBounds;
ctx.Save ();
DirtyRect += DragImageBounds;
IsDirty = true;
}
-
+
#if DEBUG_CLIP_RECTANGLE
ctx.LineWidth = 1;
for (int i = 0; i < clipping.NumRectangles; i++)
ctx.Rectangle(clipping.GetRectangle(i));
ctx.Stroke ();
-
+
#endif
#if VKVG
surf.Flush ();
#endif
-
+
clipping.Reset ();
PerformanceMeasure.End (PerformanceMeasure.Kind.Drawing);
IsDirty = true;
-
+
#if !VKVG
drawTextCursor (ctx);
#endif
debugHighlightFocus (ctx);
-
+
DbgLogger.EndEvent (DbgEvtType.ProcessDrawing, true);
}
#endregion
break;
if (newW.AlwaysOnTop || !w.AlwaysOnTop)
break;
-
+
ptr++;
}
}
lock (UpdateMutex)
GraphicTree.Insert (ptr, g);
-
+
g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
return g;
/// <summary>
/// Resize the interface. This function should be called by the host
- /// when window resize event occurs.
+ /// when window resize event occurs.
/// </summary>
/// <param name="bounds">bounding box of the interface</param>
public virtual void ProcessResize(Rectangle bounds){
public MouseCursor MouseCursor {
get => cursor;
set {
-
+
if (value == cursor)
return;
cursor = value;
default:
currentCursor = XCursor.Create (this, cursor);
break;
- }
-
+ }
+
currentCursor.Set (hWin);
//MouseCursorChanged.Raise (this,new MouseCursorChangedEventArgs(cursor));
}
}
-
+
Point stickyMouseDelta = default;
internal Widget stickedWidget = null;
if (HoverOrDropTarget != null) {
resetTooltip ();
- //check topmost graphicobject first
+ //check topmost graphicobject first
Widget topContainer = HoverOrDropTarget;
while (topContainer.LogicalParent is Widget w)
- topContainer = w;
-
+ topContainer = w;
+
int indexOfTopContainer = GraphicTree.IndexOf (topContainer);
if (indexOfTopContainer != 0) {
for (int i = 0; i < indexOfTopContainer; i++) {//check all top containers that are at a higher level
} else {
if (DragAndDropInProgress && dragndropHover == DragAndDropOperation.DropTarget)
DragAndDropOperation.DropTarget.onDragLeave (this, DragAndDropOperation);
- //seek upward from last focused graph obj's
+ //seek upward from last focused graph obj's
while (HoverOrDropTarget.FocusParent != null) {
if (!DragAndDropInProgress)
HoverWidget.onMouseLeave (this, e);
else
HoverWidget.onMouseMove (this, e);
return true;
- }
+ }
}
}
}
lastMouseDownEvent = new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press);
- if (HoverWidget == null)
+ if (HoverWidget == null)
return false;
HoverWidget.onMouseDown (this, lastMouseDownEvent);
mouseRepeatTimer.Reset ();
lastMouseDownEvent = null;
- if (DragAndDropInProgress) {
+ if (DragAndDropInProgress) {
if (DragAndDropOperation.DropTarget != null)
DragAndDropOperation.DragSource.onDrop (this, DragAndDropOperation);
else
_activeWidget.onMouseUp (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Release));
- if (_activeWidget == null) {
+ if (_activeWidget == null) {
DbgLogger.SetMsg (DbgEvtType.MouseUp, "[BUG]Mystery reset of _activeWidget");
return true;
}
// if (!lastActive.MouseIsIn (Mouse.Position)) {
// ProcessMouseMove (Mouse.X, Mouse.Y);
// }
-
+
return true;
} finally {
DbgLogger.EndEvent (DbgEvtType.MouseUp);
<HorizontalStack Height='Fit'>
<Label Text='TotalWidgetActive:' Width='50%'/>
<Label Text='{TotalWidgetActive}' TextAlignment='Right'/>
- </HorizontalStack>
+ </HorizontalStack>
<HorizontalStack Height='Fit'>
<Label Text='TotalWidgetInGraphicTree:' Width='50%'/>
<Label Text='{TotalWidgetInGraphicTree}' TextAlignment='Right'/>
").DataSource = this;
}
#endif
-
+
//Keyboard.SetKeyState((Crow.Key)Key,true);
lastKeyDownEvt = new KeyEventArgs (key, true);
}
void ToolTipContainer_LayoutChanged (object sender, LayoutingEventArgs e)
{
- Widget ttc = sender as Widget;
-
+ Widget ttc = sender as Widget;
+
//tooltip container datasource is the widget triggering the tooltip
Rectangle r = ttc?.DataSource is Widget w ? ScreenCoordinates (w.Slot) : ClientRectangle;
ctxMenuContainer.BubbleMouseEvent = DeviceEventType.None;
ctxMenuContainer.LogicalParent = go;
ctxMenuContainer.DataSource = go;
-
+
PutOnTop (ctxMenuContainer, true);
}
//OnMouseMove (MousePosition.X, MousePosition.Y);
HoverWidget = ctxMenuContainer;
- ctxMenuContainer.onMouseEnter (ctxMenuContainer, new MouseMoveEventArgs (MousePosition.X, MousePosition.Y, 0, 0));
+ ctxMenuContainer.onMouseEnter (ctxMenuContainer, new MouseMoveEventArgs (MousePosition.X, MousePosition.Y, 0, 0));
}
#endregion
set { throw new NotImplementedException (); }
}
- public Rectangle ClientRectangle => clientRectangle;
+ public Rectangle ClientRectangle => clientRectangle;
+ public Rectangle GetClientRectangleForChild (ILayoutable child) => clientRectangle;
public Interface HostContainer => this;
public Rectangle getSlot () => ClientRectangle;
Enum enumValue;
UInt32 bitFieldExcludeMask;
Type enumType;
- bool enumTypeIsBitsfield;
+ bool enumTypeIsBitsfield, forceRadioButton;
string rbStyle, iconsPrefix, iconsExtension;
#endregion
/// </summary>
[DefaultValue (null)]
public string RadioButtonStyle {
- get { return rbStyle; }
+ get => rbStyle;
set {
if (rbStyle == value)
return;
}
}
/// <summary>
+ /// if enum has the 'Flag' attribte, CheckBox will be used. RadioButton may still be forced by
+ /// setting 'ForceRadioButton'='true'
+ /// </summary>
+ /// <value></value>
+ [DefaultValue (false)]
+ public bool ForceRadioButton {
+ get => forceRadioButton;
+ set {
+ if (forceRadioButton == value)
+ return;
+ forceRadioButton = value;
+ NotifyValueChangedAuto (forceRadioButton);
+ }
+ }
+ /// <summary>
/// use to define the colors of the 3d border
/// </summary>
[DefaultValue(null)]
}
d += c.Slot.Height + Spacing;
}
- }
+ }
DbgLogger.EndEvent(DbgEvtType.GOComputeChildrenPositions);
}
Widget stretchedGO = null;
protected void setChildWidth (Widget w, int newW) {
if (w.MaximumSize.Width > 0)
newW = Math.Min (newW, w.MaximumSize.Width);
-
+
if (newW == w.Slot.Width)
return;
-
+
w.Slot.Width = newW;
w.IsDirty = true;
w.LayoutChanged -= OnChildLayoutChanges;
protected void setChildHeight (Widget w, int newH) {
if (w.MaximumSize.Height > 0)
newH = Math.Min (newH, w.MaximumSize.Height);
-
+
if (newH == w.Slot.Height)
return;
w.LastSlots.Height = w.Slot.Height;
DbgLogger.SetMsg(DbgEvtType.GOAdjustStretchedGo, $"new height={newH}");
}
- internal void adjustStretchedGo (LayoutingType lt) {
+ internal void adjustStretchedGo (LayoutingType lt) {
if (stretchedGO == null)
return;
//Console.WriteLine ($"adjust stretched go: {stretchedGO} {lt}");
DbgLogger.StartEvent(DbgEvtType.GOAdjustStretchedGo, this);
if (lt == LayoutingType.Width)
setChildWidth (stretchedGO, Math.Max (
- ClientRectangle.Width - contentSize.Width - Spacing * (Children.Count - 1), stretchedGO.MinimumSize.Width));
+ ClientRectangle.Width - contentSize.Width - Spacing * (Children.Count - 1), stretchedGO.MinimumSize.Width));
else
setChildHeight (stretchedGO, Math.Max (
ClientRectangle.Height - contentSize.Height - Spacing * (Children.Count - 1), stretchedGO.MinimumSize.Height));
}else if (child.Height == Measure.Stretched)
child.RegisterForLayouting (LayoutingType.Height);
else
- contentSize.Height += child.LastSlots.Height;
+ contentSize.Height += child.LastSlots.Height;
}
public override void RemoveChild (Widget child) {
if (child != stretchedGO) {
/// excedental child (above grid sizing) are ignored
/// and invisible child keep their place in the grid
/// </summary>
- public class Grid : Group
- {
+ public class Grid : Group
+ {
#region CTOR
protected Grid () : base(){}
public Grid(Interface iface) : base(iface)
- {
+ {
}
#endregion
#region Private fields
- int _spacing;
+ int _spacing;
int _columnCount;
int _rowCount;
#endregion
#region Public Properties
- [DefaultValue(2)]
- public int Spacing
- {
+ [DefaultValue(2)]
+ public int Spacing
+ {
get { return _spacing; }
- set { _spacing = value; }
- }
- [DefaultValue(2)]
- public virtual int ColumnCount
- {
- get { return _columnCount; }
- set {
+ set { _spacing = value; }
+ }
+ [DefaultValue(2)]
+ public virtual int ColumnCount
+ {
+ get { return _columnCount; }
+ set {
if (_columnCount == value)
return;
NotifyValueChangedAuto (ColumnCount);
this.RegisterForLayouting (LayoutingType.ArrangeChildren);
}
- }
+ }
[DefaultValue(2)]
public virtual int RowCount
{
get { return _rowCount; }
- set {
+ set {
if (_rowCount == value)
return;
}
}
public virtual int CaseWidth {
- get { return (Slot.Width - (ColumnCount - 1) * Spacing) / ColumnCount; }
+ get => (Slot.Width - (ColumnCount - 1) * Spacing) / ColumnCount;
}
public virtual int CaseHeight {
- get { return (Slot.Height - (RowCount - 1) * Spacing) / RowCount; }
+ get => (Slot.Height - (RowCount - 1) * Spacing) / RowCount;
}
#endregion
{
RegisteredLayoutings &= (~layoutType);
- if (layoutType == LayoutingType.ArrangeChildren) {
+ if (layoutType == LayoutingType.ArrangeChildren) {
ComputeChildrenPositions ();
//if no layouting remains in queue for item, registre for redraw
if (RegisteredLayoutings == LayoutingType.None && IsDirty)
IFace.EnqueueForRepaint (this);
-
+
return true;
}
}
#endregion
-
+
}
}
return;
}
childrenRWLock.EnterWriteLock ();
- try {
+ try {
g.Parent = this;
Children.Insert (idx, g);
} finally {
tallestChild = g;
contentSize.Height = g.LastSlots.Height;
}
-
- g.LayoutChanged += OnChildLayoutChanges;
+
+ g.LayoutChanged += OnChildLayoutChanges;
g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
}
public override void ClearChildren()
if (Children.Count > 0) {
if (lt == LayoutingType.Width) {
//if (largestChild == null)
- searchLargestChild ();
+ searchLargestChild ();
} else {
//if (tallestChild == null)
- searchTallestChild ();
+ searchTallestChild ();
}
}
return base.measureRawSize (lt);
}
public override void OnLayoutChanges (LayoutingType layoutType)
- {
+ {
/*if (!IsVisible)
return;*/
base.OnLayoutChanges (layoutType);
if (largestChild == null && !forceMeasure)
searchLargestChild (true);
} finally {
- childrenRWLock.ExitReadLock ();
+ childrenRWLock.ExitReadLock ();
DbgLogger.EndEvent (DbgEvtType.GOSearchLargestChild);
}
}
total += 1 + child.ChildCount;
return total;
} finally {
- childrenRWLock.ExitReadLock ();
- }
+ childrenRWLock.ExitReadLock ();
+ }
}
}
#endif
ILayoutable LogicalParent { get; set; }
Rectangle ClientRectangle { get; }
+ Rectangle GetClientRectangleForChild (ILayoutable child);
Rectangle getSlot();
bool ArrangeChildren { get; }
public static Column Parse (string str) {
if (string.IsNullOrEmpty (str))
- return null;
+ return null;
Column c = new Column();
string[] tmp = str.Split (',');
c.Caption = tmp[0];
for (int i = 0; i < HeaderRow.Children.Count; i++) {
if (row.Children.Count <= i)
continue;
- setRowCellWidth (row.Children[i], HeaderRow.Children[i].Slot.Width);
+ setRowCellWidth (row.Children[i], HeaderRow.Children[i].Slot.Width);
row.Children[i].Slot.X = HeaderRow.Children[i].Slot.X;
}
}
row.Margin = rowsMargin;
childrenRWLock.ExitReadLock ();
}
- }
- //int lineWidth;
+ }
+ //int lineWidth;
public ObservableList<Column> Columns {
get => columns;
set {
columns = value;
if (columns != null) {
- createHeaderRow ();
+ createHeaderRow ();
columns.ListAdd += Ol_AddColumn;
columns.ListAdd += Ol_RemoveColumn;
}
if (Columns == null || headerCellITor == null)
return;
HeaderRow = new HorizontalStack(IFace, "TableHeaderRow") {Spacing = ColumnSpacing};
- InsertChild (0, HeaderRow);
+ InsertChild (0, HeaderRow);
foreach (Column c in Columns) {
Widget cell = headerCellITor.CreateInstance();
cell.LayoutChanged += onHeaderCell_LayoutChanges;
cell.DataSource = c;
}
}
-
+
void Ol_AddColumn (object sender, ListChangedEventArg e) {
HeaderRow.InsertChild (e.Index, headerCellITor.CreateInstance());
HeaderRow.DataSource = e.Element;
Widget g = sender as Widget;
int cIdx = HeaderRow.Children.IndexOf (g);
if (cIdx < Columns.Count && Columns[cIdx].Width.IsFit)
- searchLargestChildInColumn (cIdx);
+ searchLargestChildInColumn (cIdx);
childrenRWLock.EnterReadLock ();
for (int i = 1; i < Children.Count; i++) {
TableRow row = Children[i] as TableRow;
}
protected void setRowCellWidth (Widget w, int newW) {
if (newW == w.Slot.Width)
- return;
+ return;
w.Slot.Width = newW;
w.IsDirty = true;
w.OnLayoutChanges (LayoutingType.Width);
w.LastSlots.Width = w.Slot.Width;
w.RegisterForRedraw ();
- }
+ }
public override void ClearChildren()
{
childrenRWLock.EnterReadLock ();
try {
c.LargestChild = null;
- int largestWidth = 0;
+ int largestWidth = 0;
for (int i = 1; i < Children.Count; i++) {
TableRow row = Children[i] as TableRow;
if (!row.IsVisible || row.Children.Count <= i)
//HeaderRow.adjustStretchedGo (LayoutingType.Width);
}
- int splitIndex = -1;
- const int minColumnSize = 10;
+ int splitIndex = -1;
+ const int minColumnSize = 10;
public override void onMouseMove(object sender, MouseMoveEventArgs e)
{
-
+
if (Columns != null && 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 (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;
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}");
+ //Console.WriteLine ($"left:{HeaderRow.Children[splitIndex].Slot.Left} right:{HeaderRow.Children[splitIndex+1].Slot.Right} splitPos:{splitPos} m:{m}");
} else {
- splitIndex = -1;
+ splitIndex = -1;
for (int i = 0; i < Columns.Count - 1; i++)
{
Rectangle r = HeaderRow.Children[i].Slot;
}
}
base.onMouseMove(sender, e);
- }
+ }
protected override void onDraw (Context gr) {
if (Columns != null && columns.Count > 0 && HeaderRow != null) {
Rectangle cb = ClientRectangle;
-
+
Foreground.SetAsSource (IFace, gr, cb);
if (BorderLineWidth > 0) {
gr.LineWidth = BorderLineWidth;
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;
+ 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.Stroke ();
}
-
+
}
DbgLogger.EndEvent (DbgEvtType.GODraw);
- }
+ }
}
}
public event EventHandler<EventArgs> ChildrenCleared;
#endregion
public override void ChildrenLayoutingConstraints(ILayoutable layoutable, ref LayoutingType layoutType)
- => layoutType &= (~(LayoutingType.X|LayoutingType.Width));
+ => layoutType &= (~(LayoutingType.X|LayoutingType.Width));
public Table Table => Parent as Table;
internal Widget tallestChild = null;
}
childrenRWLock.EnterWriteLock ();
- try {
+ try {
g.Parent = this;
Children.Insert (idx, g);
- } finally {
+ } finally {
childrenRWLock.ExitWriteLock ();
}
contentSize.Height = g.LastSlots.Height;
}
-
+
g.LayoutChanged += OnChildLayoutChanges;
g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
}
Children.Remove(child);
child.Parent = null;
child.LogicalParent = null;
- } finally {
+ } finally {
childrenRWLock.ExitWriteLock ();
}
public override int measureRawSize (LayoutingType lt)
{
DbgLogger.StartEvent(DbgEvtType.GOMeasure, this);
- try {
+ try {
if (lt == LayoutingType.Height && Children.Count > 0 && tallestChild == null)
- searchTallestChild ();
+ searchTallestChild ();
return base.measureRawSize (lt);
} finally {
- DbgLogger.EndEvent(DbgEvtType.GOMeasure);
+ DbgLogger.EndEvent(DbgEvtType.GOMeasure);
}
- }
+ }
public override void OnLayoutChanges (LayoutingType layoutType)
{
base.OnLayoutChanges (layoutType);
childrenRWLock.ExitReadLock ();
}
}
- }
+ }
public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg)
{
DbgLogger.StartEvent(DbgEvtType.GOOnChildLayoutChange, this);
BindingFlags.Instance | BindingFlags.NonPublic);
static MethodInfo miDesignAddValLoc = typeof(Widget).GetMethod("design_add_iml_location",
BindingFlags.Instance | BindingFlags.NonPublic);
-
+
public volatile bool design_HasChanged = false;
public string design_id;
public int design_line;
//public Dictionary<string,FileLocation> design_iml_locations = new Dictionary<string, FileLocation>();
public Dictionary<string,FileLocation> design_style_locations = new Dictionary<string, FileLocation>();
- internal void design_add_style_location (string memberName, string path, int line, int col) {
+ internal void design_add_style_location (string memberName, string path, int line, int col) {
if (design_style_locations.ContainsKey(memberName)){
System.Diagnostics.Debug.WriteLine ("default value localtion already set for {0}{1}.{2}", this.GetType().Name, this.design_id, memberName);
return;
// }
// design_iml_locations.Add(memberName, new FileLocation(path,line,col));
// }
-
+
public virtual bool FindByDesignID(string designID, out Widget go){
go = null;
if (this.design_id == designID){
public virtual void getIML(XmlDocument doc, XmlNode parentElem) {
if (this.design_isTGItem)
return;
-
+
XmlElement xe = doc.CreateElement(this.GetType().Name);
foreach (KeyValuePair<string,string> kv in design_iml_values) {
parentElem.AppendChild (xe);
}
public Surface CreateIcon (int dragIconSize = 32) {
-#if VKVG
+#if VKVG
Surface di = new Surface (IFace.vkvgDevice, dragIconSize, dragIconSize);
#else
ImageSurface di = new ImageSurface (Format.Argb32, dragIconSize, dragIconSize);
}
return di;
}
- public string DesignName {
- get { return GetType ().Name + design_id; }
- }
+ public string DesignName {
+ get { return GetType ().Name + design_id; }
+ }
#endif
#region IDisposable implementation
protected bool disposed = false;
- public void Dispose(){
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- ~Widget(){
+ public void Dispose(){
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ ~Widget(){
Dispose(false);
}
protected virtual void Dispose(bool disposing){
disposed = true;
#if DEBUG_STATS
TotalWidgetDisposed++;
-#endif
+#endif
DbgLogger.EndEvent (DbgEvtType.Disposing);
}
#region IValueChange implementation
/// <summary>
/// Raise to notify that the value of a property has changed, the binding system
- /// rely mainly on this event. the member name may not be present in the class, this is
+ /// rely mainly on this event. the member name may not be present in the class, this is
/// used in **propertyless** bindings, this allow to raise custom named events without needing
/// to create an new one in the class or a new property.
/// </summary>
parent = value;
Slot = LastSlots = default(Rectangle);
parentRWLock.ExitWriteLock();
-
+
onParentChanged (this, e);
}
}
/// <summary>
/// Mouse routing need to go back to logical parent for popups
/// </summary>
- internal Widget FocusParent => (parent is Interface ? LogicalParent : parent) as Widget;
+ internal Widget FocusParent => (parent is Interface ? LogicalParent : parent) as Widget;
[XmlIgnore]public ILayoutable LogicalParent {
get { return logicalParent == null ? Parent : logicalParent; }
return cb;
}
}
+ public virtual Rectangle GetClientRectangleForChild (ILayoutable child) => ClientRectangle;
/// <summary>
/// Compute rectangle position on surface of the context. It ma be the first cached surface in parenting chain,
/// or the top backend surface if no cached widget is part of the current widget tree.
public virtual Rectangle ScreenCoordinates (Rectangle r){
try {
return
- Parent.ScreenCoordinates(r) + Parent.getSlot().Position + Parent.ClientRectangle.Position;
+ Parent.ScreenCoordinates(r) + Parent.getSlot().Position + Parent.ClientRectangle.Position;
} catch (Exception ex) {
Debug.WriteLine (ex);
return default(Rectangle);
[XmlIgnore]public virtual Measure HeightPolicy { get {
return Height.IsFit ? Measure.Fit : Measure.Stretched; } }
/// <summary>
- /// Indicate that this object may received focus or not, if not focusable all the descendants are
+ /// Indicate that this object may received focus or not, if not focusable all the descendants are
/// affected.
/// </summary>
[DesignCategory ("Behaviour")][DefaultValue(false)]
onUnfocused (this, null);
NotifyValueChangedAuto (hasFocus);
}
- }
+ }
/// <summary>
- /// true if this control is active, this means that mouse has been pressed in it and not yet released. It could
+ /// true if this control is active, this means that mouse has been pressed in it and not yet released. It could
/// be used for other two states periferic action.
/// </summary>
[XmlIgnore]public virtual bool IsActive {
isHover = value;
if (isHover) {
- if (stickyMouseEnabled && stickyMouse > 0)
- IFace.stickedWidget = this;
+ if (stickyMouseEnabled && stickyMouse > 0)
+ IFace.stickedWidget = this;
Hover.Raise (this, null);
}
return;
stickyMouse = value;
NotifyValueChangedAuto (stickyMouse);
- }
- }
+ }
+ }
/// <summary>
/// Boolean for enabling or not the sticky mouse mechanic
/// </summary>
return;
stickyMouseEnabled = value;
NotifyValueChangedAuto (stickyMouseEnabled);
- }
- }
+ }
+ }
/// <summary>
/// Determine Cursor when mouse is Hover.
/// </summary>
NotifyValueChangedAuto (background);
RegisterForRedraw ();
if (background is SolidColor sc && sc.Equals (Colors.Clear))
- clearBackground = true;
+ clearBackground = true;
}
}
/// <summary>
/// </summary>
[DesignCategory ("Appearance")][DefaultValue(true)]
public virtual bool IsVisible {
- get => isVisible;
+ get => isVisible;
set {
if (value == isVisible)
return;
- isVisible = value;
-
+ isVisible = value;
+
/*if (!isVisible)
unshownPostActions ();
RegisterForLayouting (LayoutingType.Sizing);*/
- if (isVisible){
+ if (isVisible){
IsDirty = true;
} else {
- unshownPostActions ();
+ unshownPostActions ();
}
- RegisterForLayouting(LayoutingType.Sizing);
+ RegisterForLayouting(LayoutingType.Sizing);
NotifyValueChangedAuto (isVisible);
}
string styleKey = style;
if (!string.IsNullOrEmpty (style)) {
if (IFace.Styling.ContainsKey (style))
- styling.Add (IFace.Styling [style]);
+ styling.Add (IFace.Styling [style]);
}
//check the whole type hierarchy for styling
Type styleType = thisType;
dm = new DynamicMethod("dyn_loadDefValues", null, new Type[] { typeof (object) }, thisType, true);
- il = dm.GetILGenerator(256);
+ il = dm.GetILGenerator(256);
il.DeclareLocal(typeof (object));//store root
il.Emit(OpCodes.Nop);
//set local GraphicObject to root object passed as 1st argument
if (!getDefaultEvent(ei, styling, out expression))
continue;
//TODO:dynEventHandler could be cached somewhere, maybe a style instanciator class holding the styling delegate and bound to it.
- foreach (string exp in expression.Split (';')) {
+ foreach (string exp in expression.Split (';')) {
//foreach (string exp in CompilerServices.splitOnSemiColumnOutsideAccolades(expression)) {
-
+
string trimed = exp.Trim();
if (trimed.StartsWith ("{", StringComparison.Ordinal)){
il.Emit (OpCodes.Ldloc_0);//load this as 1st arg of event Add
#endregion
public virtual Widget FindByName(string nameToFind)
- => string.Equals(nameToFind, name, StringComparison.Ordinal) ? this : null;
+ => string.Equals(nameToFind, name, StringComparison.Ordinal) ? this : null;
public virtual T FindByType<T> () //where T : Widget
- => this is T t? t : default(T);
+ => this is T t? t : default(T);
public virtual bool Contains(Widget goToFind){
return false;
}
allowDrop = value;
NotifyValueChanged ("AllowDrop", allowDrop);
}
- }
+ }
/// <summary>
/// Semicolon separated list of accepted types as dropped widget.
/// </summary>
IsDragged = true;
StartDrag.Raise (this, IFace.DragAndDropOperation);
#if DEBUG_DRAGNDROP
- Debug.WriteLine(this.ToString() + " : START DRAG => " + e.ToString());
+ Debug.WriteLine(this.ToString() + " : START DRAG => " + e.ToString());
#endif
}
- protected virtual void onDragEnter (object sender, DragDropEventArgs e){
- e.DropTarget = this;
+ protected virtual void onDragEnter (object sender, DragDropEventArgs e){
+ e.DropTarget = this;
DragEnter.Raise (this, e);
#if DEBUG_DRAGNDROP
Debug.WriteLine(this.ToString() + " : DRAG Enter => " + e.ToString());
#endif
}
- public virtual void onDragLeave (object sender, DragDropEventArgs e){
+ public virtual void onDragLeave (object sender, DragDropEventArgs e){
DragLeave.Raise (this, e);
#if DEBUG_DRAGNDROP
Debug.WriteLine (this.ToString () + " : DRAG Leave => " + e.ToString ());
Debug.WriteLine(this.ToString() + " : END DRAG => " + e.ToString());
#endif
}
- public virtual void onDrop (object sender, DragDropEventArgs e){
+ public virtual void onDrop (object sender, DragDropEventArgs e){
IsDragged = false;
Drop.Raise (this, e);
//e.DropTarget.onDragLeave (this, e);//raise drag leave in target
Debug.WriteLine(this.ToString() + " : DROP => " + e.ToString());
#endif
}
- public bool IsDropTarget => IFace.DragAndDropOperation?.DropTarget == this;
+ public bool IsDropTarget => IFace.DragAndDropOperation?.DropTarget == this;
#endregion
#region Queuing
DbgLogger.StartEvent (DbgEvtType.GOClippingRegistration, this);
parentRWLock.EnterReadLock ();
- if (parent != null) {
+ if (parent != null) {
parent.RegisterClip (LastPaintedSlot);
parent.RegisterClip (Slot);
}else {
//we register clip in the parent, if it's dirty, all children will be redrawn
if (IsDirty && CacheEnabled) {
DbgLogger.SetMsg (DbgEvtType.GORegisterClip, $"regclip canceled Dirty:{IsDirty} Cached:{CacheEnabled}");
- return;
+ return;
}
Rectangle cb = ClientRectangle;
Rectangle r = clip + cb.Position;
r.Height -= r.Bottom - cb.Bottom;*/
if (r.Width < 0 || r.Height < 0){
DbgLogger.SetMsg (DbgEvtType.GORegisterClip, $"regclip canceled size w:{r.Width} h:{r.Height}");
- return;
+ return;
}
if (cacheEnabled)
Clipping.UnionRectangle (r);
if (Parent == null){
DbgLogger.SetMsg (DbgEvtType.GORegisterClip, "clip chain aborded (no parent)");
- return;
+ return;
}
/*Widget p = Parent as Widget;
if (p?.IsDirty == true && p?.CacheEnabled == true){
Console.WriteLine ($"parent.regclip canceled p.Dirty:{p?.IsDirty} Cached:{p?.CacheEnabled}: {this.ToString()}");
- return;
+ return;
}*/
Parent.RegisterClip (r + Slot.Position);
} finally {
}
DbgLogger.StartEvent(DbgEvtType.GORegisterForGraphicUpdate, this);
- IsDirty = true;
+ IsDirty = true;
if (Width.IsFit || Height.IsFit)
RegisterForLayouting (LayoutingType.Sizing);
else
/// of the drawing could take place in the onDraw method, and the markers (single line, rectangle, ...)
/// could be drawn in the Paint method. Such widget must have 'CacheEnabled=true' and to simply update the
/// markers without a full redraw, just call 'RegisterForRepaint'.
- ///
+ ///
/// </remark>
public void RegisterForRepaint () {
if (RequiredLayoutings == LayoutingType.None)// && !IsDirty)
return lt == LayoutingType.Width ?
contentSize.Width + 2 * margin : contentSize.Height + 2 * margin;
} finally {
- DbgLogger.EndEvent(DbgEvtType.GOMeasure);
+ DbgLogger.EndEvent(DbgEvtType.GOMeasure);
}
}
}
return false;
}
- protected bool stretchedInFit (LayoutingType lt) {
-
+ protected bool stretchedInFit (LayoutingType lt) {
+
if (Parent == null)
return false;
Widget p = Parent as Widget;
if (lt == LayoutingType.Width) {
if (!Width.IsRelativeToParent)
- return false;
+ return false;
while (p.Width.IsRelativeToParent) {
p = p.Parent as Widget;
if (p == null)
return p.Width.IsFit;
}
if (!Height.IsRelativeToParent)
- return false;
+ return false;
while (p.Height.IsRelativeToParent) {
p = p.Parent as Widget;
if (p == null)
/// arrange children in the x direction.
/// </summary>
/// <param name="layoutable">The children that is calling the constraints</param>
- /// <param name="layoutType">The currently registering layouting types</param>
+ /// <param name="layoutType">The currently registering layouting types</param>
public virtual void ChildrenLayoutingConstraints(ILayoutable layoutable, ref LayoutingType layoutType){ }
/// <summary> Query a layouting for the type pass as parameter, redraw only if layout changed. </summary>
-
+
internal ReaderWriterLockSlim layoutMutex = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
public virtual void RegisterForLayouting(LayoutingType layoutType){
if (disposed) {
return;
}
- parentRWLock.EnterReadLock ();
+ parentRWLock.EnterReadLock ();
try {
if (Parent == null)
layoutMutex.EnterWriteLock ();
try {
-
-
+
+
//prevent queueing same LayoutingType for this
layoutType &= (~RegisteredLayoutings);
if (layoutType == LayoutingType.None)
return;
-
+
//dont set position for stretched item
if (Width == Measure.Stretched)
layoutType &= (~LayoutingType.X);
RequiredLayoutings |= layoutType;
} finally {
- layoutMutex.ExitWriteLock ();
+ layoutMutex.ExitWriteLock ();
}
DbgLogger.StartEvent (DbgEvtType.GOLockLayouting, this);
if (left == 0) {
if (Parent.RequiredLayoutings.HasFlag (LayoutingType.Width) ||
- RequiredLayoutings.HasFlag (LayoutingType.Width))
+ RequiredLayoutings.HasFlag (LayoutingType.Width))
return false;
switch (horizontalAlignment) {
Slot.X = 0;
break;
case HorizontalAlignment.Right:
- Slot.X = Parent.ClientRectangle.Width - Slot.Width;
+ Slot.X = Parent.GetClientRectangleForChild(this).Width - Slot.Width;
break;
case HorizontalAlignment.Center:
- Slot.X = Parent.ClientRectangle.Width / 2 - Slot.Width / 2;
+ Slot.X = Parent.GetClientRectangleForChild(this).Width / 2 - Slot.Width / 2;
break;
}
} else
if (top == 0) {
if (Parent.RequiredLayoutings.HasFlag (LayoutingType.Height) ||
- RequiredLayoutings.HasFlag (LayoutingType.Height))
+ RequiredLayoutings.HasFlag (LayoutingType.Height))
return false;
switch (verticalAlignment) {
Slot.Y = 0;
break;
case VerticalAlignment.Bottom:
- Slot.Y = Parent.ClientRectangle.Height - Slot.Height;
+ Slot.Y = Parent.GetClientRectangleForChild(this).Height - Slot.Height;
break;
case VerticalAlignment.Center:
- Slot.Y = Parent.ClientRectangle.Height / 2 - Slot.Height / 2;
+ Slot.Y = Parent.GetClientRectangleForChild(this).Height / 2 - Slot.Height / 2;
break;
}
} else
} else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Width))
return false;
else if (Width == Measure.Stretched)
- Slot.Width = Parent.ClientRectangle.Width;
+ Slot.Width = Parent.GetClientRectangleForChild(this).Width;
else
- Slot.Width = (int)Math.Round ((double)(Parent.ClientRectangle.Width * Width) / 100.0);
+ Slot.Width = (int)Math.Round ((double)(Parent.GetClientRectangleForChild(this).Width * Width) / 100.0);
if (Slot.Width < 0)
return false;
//size constrain
if (Slot.Width < minimumSize.Width)
- Slot.Width = minimumSize.Width;
+ Slot.Width = minimumSize.Width;
else if (maximumSize.Width > 0 && Slot.Width > maximumSize.Width)
Slot.Width = maximumSize.Width;
-
+
} else
Slot.Width = 0;
} else if (Parent.RegisteredLayoutings.HasFlag (LayoutingType.Height))
return false;
else if (Height == Measure.Stretched)
- Slot.Height = Parent.ClientRectangle.Height;
+ Slot.Height = Parent.GetClientRectangleForChild(this).Height;
else
- Slot.Height = (int)Math.Round ((double)(Parent.ClientRectangle.Height * Height) / 100.0);
+ Slot.Height = (int)Math.Round ((double)(Parent.GetClientRectangleForChild(this).Height * Height) / 100.0);
if (Slot.Height < 0)
return false;
Slot.Height = minimumSize.Height;
else if (maximumSize.Height > 0 && Slot.Height > maximumSize.Height)
Slot.Height = maximumSize.Height;
-
+
} else
Slot.Height = 0;
#region Rendering
/// <summary> This is the common overridable drawing routine to create new widget </summary>
protected virtual void onDraw(Context gr)
- {
+ {
DbgLogger.StartEvent(DbgEvtType.GODraw, this);
Rectangle rBack = new Rectangle (Slot.Size);
onDraw (gr);
}
- IsDirty = false;
+ IsDirty = false;
DbgLogger.EndEvent (DbgEvtType.GORecreateCache);
}
protected void paintCache(Context ctx, Rectangle rb) {
- DbgLogger.StartEvent(DbgEvtType.GOPaintCache, this);
+ DbgLogger.StartEvent(DbgEvtType.GOPaintCache, this);
if (clearBackground) {
ctx.Operator = Operator.Clear;
ctx.Rectangle (rb);
ctx.Operator = Operator.Over;
}
- ctx.SetSource (bmp, rb.X, rb.Y);
+ ctx.SetSource (bmp, rb.X, rb.Y);
ctx.Paint ();
#if VKVG
ctx.Flush ();
#endif
- DbgLogger.EndEvent(DbgEvtType.GOPaintCache);
+ DbgLogger.EndEvent(DbgEvtType.GOPaintCache);
}
protected virtual void UpdateCache(Context ctx){
- DbgLogger.StartEvent(DbgEvtType.GOUpdateCache, this);
+ DbgLogger.StartEvent(DbgEvtType.GOUpdateCache, this);
paintCache (ctx, Slot + Parent.ClientRectangle.Position);
DbgLogger.AddEvent (DbgEvtType.GOResetClip, this);
- Clipping.Reset ();
+ Clipping.Reset ();
DbgLogger.EndEvent (DbgEvtType.GOUpdateCache);
}
/// <summary> Chained painting routine on the parent context of the actual cached version
#endif
DbgLogger.AddEvent (DbgEvtType.Warning);
DbgLogger.EndEvent (DbgEvtType.GOPaint);
- return;
+ return;
}
//lock (this) {
if (cacheEnabled) {
if (Slot.Width > Interface.MaxCacheSize || Slot.Height > Interface.MaxCacheSize)
cacheEnabled = false;
- }
+ }
if (cacheEnabled) {
if (IsDirty) {
paintCache (ctx, Slot + Parent.ClientRectangle.Position);
}else
UpdateCache (ctx);
- if (!IsEnabled)
- paintDisabled (ctx, Slot + Parent.ClientRectangle.Position);
+ if (!IsEnabled)
+ paintDisabled (ctx, Slot + Parent.ClientRectangle.Position);
} else {
Rectangle rb = Slot + Parent.ClientRectangle.Position;
//ctx.Save ();
if (!IsEnabled)
paintDisabled (ctx, rb);
- }
+ }
LastPaintedSlot = Slot;
//}
}
#endregion
- #region Keyboard handling
+ #region Keyboard handling
public virtual void onKeyDown(object sender, KeyEventArgs e){
if (KeyDown != null)
KeyDown.Invoke (this, e);
else if (!e.Handled)
FocusParent?.onKeyPress (sender, e);
}
- #endregion
+ #endregion
#region Mouse handling
/// <summary>
if (!parent.PointIsIn(ref m))
return false;
m -= (parent.getSlot().Position + parent.ClientRectangle.Position) ;
- return Slot.ContainsOrIsEqual (m);
+ return Slot.ContainsOrIsEqual (m);
}
public virtual bool MouseIsIn(Point m)
=> (!(isVisible & IsEnabled) || IsDragged) ? false : PointIsIn (ref m);
if (IFace.dragndropHover != this) {
IFace.dragndropHover = this;
#if DEBUG_DRAGNDROP
- Debug.WriteLine($"DragNDropHover = {this.ToString()} AllowDrop:{AllowDrop}, {IFace.DragAndDropOperation.DragSource.AllowedDropTypes}");
+ Debug.WriteLine($"DragNDropHover = {this.ToString()} AllowDrop:{AllowDrop}, {IFace.DragAndDropOperation.DragSource.AllowedDropTypes}");
#endif
if (AllowDrop && AcceptDrop (IFace.DragAndDropOperation.DragSource))
} else if (IFace.HoverWidget != this) {
onMouseEnter (this, e);
IFace.HoverWidget = this;
- }
+ }
}
public virtual void onMouseMove (object sender, MouseMoveEventArgs e)
{
- if (AllowDrag & IFace.IsDown (MouseButton.Left)) {
+ if (AllowDrag & IFace.IsDown (MouseButton.Left)) {
onStartDrag (this, new DragDropEventArgs (this, FocusParent));
return;
}
if (MouseMove != null)
- MouseMove.Invoke (this, e);
+ MouseMove.Invoke (this, e);
else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.MouseMove))
FocusParent?.onMouseMove (sender, e);
}
/// <param name="sender">The Sender of the event</param>
/// <param name="e">event arguments</param>
public virtual void onMouseDoubleClick(object sender, MouseButtonEventArgs e){
- if (MouseDoubleClick != null)
+ if (MouseDoubleClick != null)
MouseDoubleClick.Invoke (this, e);
else if (!e.Handled && BubbleMouseEvent.HasFlag (DeviceEventType.MouseClick))
FocusParent?.onMouseDoubleClick (sender, e);
MouseEnter.Raise (this, e);
}
public virtual void onMouseLeave(object sender, MouseMoveEventArgs e)
- {
+ {
MouseLeave.Raise (this, e);
}
#endregion
protected virtual void onFocused(object sender, EventArgs e){
- DbgLogger.AddEvent (DbgEvtType.FocusedWidget, this);
+ DbgLogger.AddEvent (DbgEvtType.FocusedWidget, this);
Focused.Raise (this, e);
}
protected virtual void onUnfocused(object sender, EventArgs e){
string tmp ="";
if (Parent != null)
- tmp = Parent.ToString () + tmp;
+ tmp = Parent.ToString () + tmp;
return string.IsNullOrEmpty(Name) ? tmp + "." + LogName : tmp + "." + Name;
//#endif
}
/// 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();
{
Debug.WriteLine($"[ERR]:unshownPostActions:{e}");
}
-
+
/*if (IFace.ActiveWidget != null) {
if (IsActive) {
IFace.OnMouseMove (IFace.MousePosition.X, IFace.MousePosition.Y);
}
}
-
+
/*Slot = default;
try
{
if (LastSlots.Height > 0)
OnLayoutChanges (LayoutingType.Height);
OnLayoutChanges (LayoutingType.X);
- OnLayoutChanges (LayoutingType.Y);
+ OnLayoutChanges (LayoutingType.Y);
}
catch (System.Exception ex)
{
}
LastSlots = default;
LastPaintedSlot = default;*/
- //Slot = LastSlots = default;
+ //Slot = LastSlots = LastPaintedSlot = default;
+ Slot = LastPaintedSlot = default;
}
}
}
CMDMaximize = new Command ("Maximize", () => CurrentState = Status.Maximized, "#Crow.Icons.maximize.svg", allowedStates.HasFlag (Status.Maximized));
CMDNormalize = new Command ("Normalize", () => CurrentState = Status.Normal, "#Crow.Icons.normalize.svg", false);
CMDClose = new Command ("Close", close, "#Crow.Icons.exit2.svg", true);
-
Commands = new CommandGroup(CMDMinimize, CMDNormalize, CMDMaximize, CMDClose);
}
<Authors>Jean-Philippe Bruyère</Authors>
<LangVersion>7.3</LangVersion>
- <CrowVersion>0.9.5</CrowVersion>
+ <CrowVersion>0.9.6</CrowVersion>
<CrowPackageVersion>$(CrowVersion)-beta</CrowPackageVersion>
<!-- If you dont have a native libstb on your system, enable the managed version of stb here
<CrowDebugLogEnabled>false</CrowDebugLogEnabled>
<!-- Collect several statistics on widgets-->
- <CrowDebugStatsEnabled>true</CrowDebugStatsEnabled>
+ <CrowDebugStatsEnabled>false</CrowDebugStatsEnabled>
<!-- Used only by CrowIDE and CrowEdit-->
<CrowDesignModeEnabled>false</CrowDesignModeEnabled>
lock (IFace.UpdateMutex) {
if (overlay == null) {
overlay = IFace.LoadIMLFragment<ListBox>(@"
- <ListBox Style='suggestionsListBox' Data='{Suggestions}' >
+ <ListBox Style='suggestionsListBox' Data='{Suggestions}' UseLoadingThread='False' >
<ItemTemplate>
<ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
Selected = '{Background=${ControlHighlight}}'
<Label Text='{}' HorizontalAlignment='Left' />
</ListItem>
</ItemTemplate>
- <ItemTemplate DataType='MemberInfo'>
+ <ItemTemplate DataType='System.Reflection.MemberInfo'>
<ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
Selected = '{Background=${ControlHighlight}}'
Unselected = '{Background=Transparent}'>
<Label Text='{Name}' HorizontalAlignment='Left' />
</HorizontalStack>
</ListItem>
- </ItemTemplate>
+ </ItemTemplate>
<ItemTemplate DataType='Colors'>
<ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left'
Selected = '{Background=${ControlHighlight}}'
--- /dev/null
+<Grid ColumnCount="2" RowCount="2">
+ <Label/>
+ <Label/>
+ <Label/>
+ <Label/>
+</Grid>
\ No newline at end of file