diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-09-09 17:34:45 +0000 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-09-09 17:34:45 +0000 |
| commit | e82d60c16d3f38c178235d36473c284bde735984 (patch) | |
| tree | 3cb417f35aa083b456ed7bf89aad5b29c3ed66d0 | |
| parent | 1e0a8be504708bd33d63ad5d9e03a5a7d5823ea9 (diff) | |
unshown post process slot handling, GetClientRectangleForChild added to the ILayoutable interface
| -rw-r--r-- | Crow/Crow.csproj | 2 | ||||
| -rw-r--r-- | Crow/sgKey.snk | bin | 0 -> 596 bytes | |||
| -rw-r--r-- | Crow/src/Interface.cs | 171 | ||||
| -rw-r--r-- | Crow/src/Widgets/EnumSelector.cs | 19 | ||||
| -rw-r--r-- | Crow/src/Widgets/GenericStack.cs | 14 | ||||
| -rw-r--r-- | Crow/src/Widgets/Grid.cs | 42 | ||||
| -rw-r--r-- | Crow/src/Widgets/Group.cs | 18 | ||||
| -rw-r--r-- | Crow/src/Widgets/ILayoutable.cs | 1 | ||||
| -rw-r--r-- | Crow/src/Widgets/Table.cs | 46 | ||||
| -rw-r--r-- | Crow/src/Widgets/TableRow.cs | 20 | ||||
| -rw-r--r-- | Crow/src/Widgets/Widget.cs | 216 | ||||
| -rw-r--r-- | Crow/src/Widgets/Window.cs | 1 | ||||
| -rw-r--r-- | Directory.Build.props | 4 | ||||
| -rw-r--r-- | Samples/common/src/Editor.cs | 6 | ||||
| -rw-r--r-- | Samples/common/ui/Interfaces/Experimental/testGrid.crow | 6 |
15 files changed, 310 insertions, 256 deletions
diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj index e778a55b..3b054bb4 100644 --- a/Crow/Crow.csproj +++ b/Crow/Crow.csproj @@ -2,7 +2,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <!-- <TargetFrameworks>netstandard2.0</TargetFrameworks>--> - <TargetFrameworks>netstandard2.1</TargetFrameworks> + <TargetFramework>netstandard2.1</TargetFramework> <AssemblyVersion>$(CrowVersion)</AssemblyVersion> <PackageVersion>$(CrowPackageVersion)</PackageVersion> diff --git a/Crow/sgKey.snk b/Crow/sgKey.snk Binary files differnew file mode 100644 index 00000000..9c8ae240 --- /dev/null +++ b/Crow/sgKey.snk diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index 632c9bbf..4bc33896 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -33,15 +33,15 @@ namespace Crow /// - 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> @@ -61,6 +61,13 @@ namespace Crow #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)) @@ -69,6 +76,10 @@ namespace Crow 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)) @@ -94,9 +105,12 @@ namespace Crow 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) @@ -117,7 +131,7 @@ namespace Crow crowAssemblies.Add (a); } catch { - } + } }*/ foreach (string assemblyName in crowAssemblyNames) { try { @@ -126,21 +140,37 @@ namespace Crow 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; @@ -219,7 +249,7 @@ namespace Crow 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 (); @@ -257,7 +287,7 @@ namespace Crow #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); @@ -270,13 +300,13 @@ namespace Crow 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) { @@ -311,7 +341,7 @@ namespace Crow 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]; @@ -387,8 +417,8 @@ namespace Crow }; #endregion - - public string WindowTitle { + + public string WindowTitle { set => Glfw3.SetWindowTitle (hWin, value); } @@ -428,9 +458,9 @@ namespace Crow disposeContextMenus (); initDictionaries (); loadStyling (); - loadThemeFiles (); + loadThemeFiles (); initContextMenus (); - } + } /// <summary> /// call Init() then enter the running loop performing ProcessEvents until running==false. /// </summary> @@ -441,7 +471,7 @@ namespace Crow Glfw3.PollEvents (); UpdateFrame (); } - + Terminate (); } public virtual void Terminate () {} @@ -598,7 +628,7 @@ namespace Crow /// <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 @@ -620,7 +650,7 @@ namespace Crow /// <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> @@ -645,7 +675,7 @@ namespace Crow lock (UpdateMutex) { if (DragImage == null) return; - clipping.UnionRectangle (lastDragImageBounds); + clipping.UnionRectangle (lastDragImageBounds); DragImage.Dispose(); DragImage = null; DragImageBounds = lastDragImageBounds = default; @@ -699,7 +729,7 @@ namespace Crow loadThemeStyle (); loadStylingFromAssembly (Assembly.GetEntryAssembly ()); foreach (Assembly a in crowAssemblies) - loadStylingFromAssembly (a); + loadStylingFromAssembly (a); loadStylingFromAssembly (Assembly.GetExecutingAssembly ()); } /// <summary> Search for .style resources in assembly </summary> @@ -709,7 +739,7 @@ namespace Crow 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); } } @@ -749,7 +779,7 @@ namespace Crow 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 () { @@ -864,11 +894,11 @@ namespace Crow 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); @@ -898,7 +928,7 @@ namespace Crow /// </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> @@ -1034,7 +1064,7 @@ namespace Crow } _focusedWidget = value; - NotifyValueChanged ("FocusedWidget", _focusedWidget); + NotifyValueChanged ("FocusedWidget", _focusedWidget); if (_focusedWidget != null) _focusedWidget.HasFocus = true; } @@ -1047,7 +1077,7 @@ namespace Crow /// 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; @@ -1086,7 +1116,7 @@ namespace Crow if (!Monitor.TryEnter (UpdateMutex)) return; - + DbgLogger.StartEvent (DbgEvtType.Update); PerformanceMeasure.Begin (PerformanceMeasure.Kind.Update); @@ -1105,7 +1135,7 @@ namespace Crow if (!clipping.IsEmpty) { if (ctx == null) { - using (ctx = new Context (surf)) + using (ctx = new Context (surf)) processDrawing (ctx); }else processDrawing (ctx); @@ -1116,8 +1146,8 @@ namespace Crow if (!vkCtx.render ()) ProcessResize (new Rectangle (0,0,(int)vkCtx.width, (int)vkCtx.height)); } -#endif - +#endif + } finally { PerformanceMeasure.End (PerformanceMeasure.Kind.Update); @@ -1130,7 +1160,7 @@ namespace Crow } #if VKVG void resizeVulkanContext () { - + } @@ -1191,8 +1221,8 @@ namespace Crow ctx.ClipPreserve (); ctx.Operator = Operator.Clear; - ctx.Fill (); - ctx.Operator = Operator.Over; + ctx.Fill (); + ctx.Operator = Operator.Over; } bool solidBackground = false; public bool SolidBackground { @@ -1210,10 +1240,10 @@ namespace Crow /// 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 (); @@ -1221,7 +1251,7 @@ namespace Crow if (SolidBackground) clear (ctx); #endif - + for (int i = GraphicTree.Count -1; i >= 0 ; i--){ Widget p = GraphicTree[i]; if (!p.IsVisible) @@ -1234,7 +1264,7 @@ namespace Crow ctx.Restore (); } - + if (lastDragImageBounds != DragImageBounds) { DirtyRect += lastDragImageBounds; ctx.Save (); @@ -1245,7 +1275,7 @@ namespace Crow DirtyRect += DragImageBounds; IsDirty = true; } - + #if DEBUG_CLIP_RECTANGLE ctx.LineWidth = 1; @@ -1253,7 +1283,7 @@ namespace Crow for (int i = 0; i < clipping.NumRectangles; i++) ctx.Rectangle(clipping.GetRectangle(i)); ctx.Stroke (); - + #endif #if VKVG @@ -1268,18 +1298,18 @@ namespace Crow 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 @@ -1359,14 +1389,14 @@ namespace Crow break; if (newW.AlwaysOnTop || !w.AlwaysOnTop) break; - + ptr++; } } lock (UpdateMutex) GraphicTree.Insert (ptr, g); - + g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); return g; @@ -1449,7 +1479,7 @@ namespace Crow /// <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){ @@ -1574,7 +1604,7 @@ namespace Crow public MouseCursor MouseCursor { get => cursor; set { - + if (value == cursor) return; cursor = value; @@ -1597,13 +1627,13 @@ namespace Crow default: currentCursor = XCursor.Create (this, cursor); break; - } - + } + currentCursor.Set (hWin); //MouseCursorChanged.Raise (this,new MouseCursorChangedEventArgs(cursor)); } } - + Point stickyMouseDelta = default; internal Widget stickedWidget = null; @@ -1663,11 +1693,11 @@ namespace Crow 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 @@ -1704,7 +1734,7 @@ namespace Crow } 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); @@ -1716,7 +1746,7 @@ namespace Crow else HoverWidget.onMouseMove (this, e); return true; - } + } } } } @@ -1762,7 +1792,7 @@ namespace Crow lastMouseDownEvent = new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press); - if (HoverWidget == null) + if (HoverWidget == null) return false; HoverWidget.onMouseDown (this, lastMouseDownEvent); @@ -1787,7 +1817,7 @@ namespace Crow mouseRepeatTimer.Reset (); lastMouseDownEvent = null; - if (DragAndDropInProgress) { + if (DragAndDropInProgress) { if (DragAndDropOperation.DropTarget != null) DragAndDropOperation.DragSource.onDrop (this, DragAndDropOperation); else @@ -1805,7 +1835,7 @@ namespace Crow _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; } @@ -1819,7 +1849,7 @@ namespace Crow // if (!lastActive.MouseIsIn (Mouse.Position)) { // ProcessMouseMove (Mouse.X, Mouse.Y); // } - + return true; } finally { DbgLogger.EndEvent (DbgEvtType.MouseUp); @@ -1879,7 +1909,7 @@ namespace Crow <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'/> @@ -1889,7 +1919,7 @@ namespace Crow ").DataSource = this; } #endif - + //Keyboard.SetKeyState((Crow.Key)Key,true); lastKeyDownEvt = new KeyEventArgs (key, true); @@ -1965,8 +1995,8 @@ namespace Crow } 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; @@ -2037,7 +2067,7 @@ namespace Crow ctxMenuContainer.BubbleMouseEvent = DeviceEventType.None; ctxMenuContainer.LogicalParent = go; ctxMenuContainer.DataSource = go; - + PutOnTop (ctxMenuContainer, true); } @@ -2046,7 +2076,7 @@ namespace Crow //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 @@ -2100,7 +2130,8 @@ namespace Crow 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; diff --git a/Crow/src/Widgets/EnumSelector.cs b/Crow/src/Widgets/EnumSelector.cs index aa77839e..c61e97f2 100644 --- a/Crow/src/Widgets/EnumSelector.cs +++ b/Crow/src/Widgets/EnumSelector.cs @@ -39,7 +39,7 @@ namespace Crow Enum enumValue; UInt32 bitFieldExcludeMask; Type enumType; - bool enumTypeIsBitsfield; + bool enumTypeIsBitsfield, forceRadioButton; string rbStyle, iconsPrefix, iconsExtension; #endregion @@ -72,7 +72,7 @@ namespace Crow /// </summary> [DefaultValue (null)] public string RadioButtonStyle { - get { return rbStyle; } + get => rbStyle; set { if (rbStyle == value) return; @@ -82,6 +82,21 @@ namespace Crow } } /// <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)] diff --git a/Crow/src/Widgets/GenericStack.cs b/Crow/src/Widgets/GenericStack.cs index 5ae3ac36..a605f02d 100644 --- a/Crow/src/Widgets/GenericStack.cs +++ b/Crow/src/Widgets/GenericStack.cs @@ -104,7 +104,7 @@ namespace Crow { } d += c.Slot.Height + Spacing; } - } + } DbgLogger.EndEvent(DbgEvtType.GOComputeChildrenPositions); } Widget stretchedGO = null; @@ -126,10 +126,10 @@ namespace Crow { 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; @@ -141,7 +141,7 @@ namespace Crow { 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; @@ -153,14 +153,14 @@ namespace Crow { 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)); @@ -248,7 +248,7 @@ namespace Crow { }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) { diff --git a/Crow/src/Widgets/Grid.cs b/Crow/src/Widgets/Grid.cs index 879f305c..14122843 100644 --- a/Crow/src/Widgets/Grid.cs +++ b/Crow/src/Widgets/Grid.cs @@ -40,33 +40,33 @@ namespace Crow /// 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; @@ -75,12 +75,12 @@ namespace Crow NotifyValueChangedAuto (ColumnCount); this.RegisterForLayouting (LayoutingType.ArrangeChildren); } - } + } [DefaultValue(2)] public virtual int RowCount { get { return _rowCount; } - set { + set { if (_rowCount == value) return; @@ -91,10 +91,10 @@ namespace Crow } } 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 @@ -151,14 +151,14 @@ namespace Crow { 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; } @@ -166,6 +166,6 @@ namespace Crow } #endregion - + } } diff --git a/Crow/src/Widgets/Group.cs b/Crow/src/Widgets/Group.cs index f13f335a..90ff4e64 100644 --- a/Crow/src/Widgets/Group.cs +++ b/Crow/src/Widgets/Group.cs @@ -58,7 +58,7 @@ namespace Crow return; } childrenRWLock.EnterWriteLock (); - try { + try { g.Parent = this; Children.Insert (idx, g); } finally { @@ -74,8 +74,8 @@ namespace Crow tallestChild = g; contentSize.Height = g.LastSlots.Height; } - - g.LayoutChanged += OnChildLayoutChanges; + + g.LayoutChanged += OnChildLayoutChanges; g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); } public override void ClearChildren() @@ -106,10 +106,10 @@ namespace Crow if (Children.Count > 0) { if (lt == LayoutingType.Width) { //if (largestChild == null) - searchLargestChild (); + searchLargestChild (); } else { //if (tallestChild == null) - searchTallestChild (); + searchTallestChild (); } } return base.measureRawSize (lt); @@ -119,7 +119,7 @@ namespace Crow } public override void OnLayoutChanges (LayoutingType layoutType) - { + { /*if (!IsVisible) return;*/ base.OnLayoutChanges (layoutType); @@ -223,7 +223,7 @@ namespace Crow if (largestChild == null && !forceMeasure) searchLargestChild (true); } finally { - childrenRWLock.ExitReadLock (); + childrenRWLock.ExitReadLock (); DbgLogger.EndEvent (DbgEvtType.GOSearchLargestChild); } } @@ -270,8 +270,8 @@ namespace Crow total += 1 + child.ChildCount; return total; } finally { - childrenRWLock.ExitReadLock (); - } + childrenRWLock.ExitReadLock (); + } } } #endif diff --git a/Crow/src/Widgets/ILayoutable.cs b/Crow/src/Widgets/ILayoutable.cs index c9148668..18cd2ccf 100644 --- a/Crow/src/Widgets/ILayoutable.cs +++ b/Crow/src/Widgets/ILayoutable.cs @@ -16,6 +16,7 @@ namespace Crow ILayoutable LogicalParent { get; set; } Rectangle ClientRectangle { get; } + Rectangle GetClientRectangleForChild (ILayoutable child); Rectangle getSlot(); bool ArrangeChildren { get; } diff --git a/Crow/src/Widgets/Table.cs b/Crow/src/Widgets/Table.cs index c712cb3d..babd4d59 100644 --- a/Crow/src/Widgets/Table.cs +++ b/Crow/src/Widgets/Table.cs @@ -49,7 +49,7 @@ namespace Crow 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]; @@ -95,7 +95,7 @@ namespace Crow 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; } } @@ -158,8 +158,8 @@ namespace Crow row.Margin = rowsMargin; childrenRWLock.ExitReadLock (); } - } - //int lineWidth; + } + //int lineWidth; public ObservableList<Column> Columns { get => columns; set { @@ -174,7 +174,7 @@ namespace Crow columns = value; if (columns != null) { - createHeaderRow (); + createHeaderRow (); columns.ListAdd += Ol_AddColumn; columns.ListAdd += Ol_RemoveColumn; } @@ -192,7 +192,7 @@ namespace Crow 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; @@ -200,7 +200,7 @@ namespace Crow cell.DataSource = c; } } - + void Ol_AddColumn (object sender, ListChangedEventArg e) { HeaderRow.InsertChild (e.Index, headerCellITor.CreateInstance()); HeaderRow.DataSource = e.Element; @@ -217,7 +217,7 @@ namespace Crow 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; @@ -244,13 +244,13 @@ namespace Crow } 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() { @@ -267,7 +267,7 @@ namespace Crow 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) @@ -290,15 +290,15 @@ namespace Crow //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; @@ -306,9 +306,9 @@ namespace Crow 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; @@ -327,7 +327,7 @@ namespace Crow } } base.onMouseMove(sender, e); - } + } protected override void onDraw (Context gr) { @@ -338,7 +338,7 @@ namespace Crow if (Columns != null && columns.Count > 0 && HeaderRow != null) { Rectangle cb = ClientRectangle; - + Foreground.SetAsSource (IFace, gr, cb); if (BorderLineWidth > 0) { gr.LineWidth = BorderLineWidth; @@ -348,7 +348,7 @@ namespace Crow 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); @@ -369,11 +369,11 @@ namespace Crow } gr.Stroke (); } - + } DbgLogger.EndEvent (DbgEvtType.GODraw); - } + } } } diff --git a/Crow/src/Widgets/TableRow.cs b/Crow/src/Widgets/TableRow.cs index 2c6db331..70370b7b 100644 --- a/Crow/src/Widgets/TableRow.cs +++ b/Crow/src/Widgets/TableRow.cs @@ -35,7 +35,7 @@ namespace Crow 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; @@ -46,10 +46,10 @@ namespace Crow } childrenRWLock.EnterWriteLock (); - try { + try { g.Parent = this; Children.Insert (idx, g); - } finally { + } finally { childrenRWLock.ExitWriteLock (); } @@ -58,7 +58,7 @@ namespace Crow contentSize.Height = g.LastSlots.Height; } - + g.LayoutChanged += OnChildLayoutChanges; g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); } @@ -76,7 +76,7 @@ namespace Crow Children.Remove(child); child.Parent = null; child.LogicalParent = null; - } finally { + } finally { childrenRWLock.ExitWriteLock (); } @@ -108,14 +108,14 @@ namespace Crow 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); @@ -134,7 +134,7 @@ namespace Crow childrenRWLock.ExitReadLock (); } } - } + } public virtual void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { DbgLogger.StartEvent(DbgEvtType.GOOnChildLayoutChange, this); diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index 24aaa695..c114fb3f 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -48,7 +48,7 @@ namespace Crow 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; @@ -60,7 +60,7 @@ namespace Crow //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; @@ -74,7 +74,7 @@ namespace Crow // } // 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){ @@ -107,7 +107,7 @@ namespace Crow 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) { @@ -119,7 +119,7 @@ namespace Crow 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); @@ -140,19 +140,19 @@ namespace Crow } 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){ @@ -180,7 +180,7 @@ namespace Crow disposed = true; #if DEBUG_STATS TotalWidgetDisposed++; -#endif +#endif DbgLogger.EndEvent (DbgEvtType.Disposing); } @@ -205,7 +205,7 @@ namespace Crow #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> @@ -368,14 +368,14 @@ namespace Crow 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; } @@ -399,6 +399,7 @@ namespace Crow 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. @@ -423,7 +424,7 @@ namespace Crow 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); @@ -700,7 +701,7 @@ namespace Crow [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)] @@ -730,9 +731,9 @@ namespace Crow 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 { @@ -760,8 +761,8 @@ namespace Crow isHover = value; if (isHover) { - if (stickyMouseEnabled && stickyMouse > 0) - IFace.stickedWidget = this; + if (stickyMouseEnabled && stickyMouse > 0) + IFace.stickedWidget = this; Hover.Raise (this, null); } @@ -807,8 +808,8 @@ namespace Crow return; stickyMouse = value; NotifyValueChangedAuto (stickyMouse); - } - } + } + } /// <summary> /// Boolean for enabling or not the sticky mouse mechanic /// </summary> @@ -820,8 +821,8 @@ namespace Crow return; stickyMouseEnabled = value; NotifyValueChangedAuto (stickyMouseEnabled); - } - } + } + } /// <summary> /// Determine Cursor when mouse is Hover. /// </summary> @@ -858,7 +859,7 @@ namespace Crow NotifyValueChangedAuto (background); RegisterForRedraw (); if (background is SolidColor sc && sc.Equals (Colors.Clear)) - clearBackground = true; + clearBackground = true; } } /// <summary> @@ -931,23 +932,23 @@ namespace Crow /// </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); } @@ -1164,7 +1165,7 @@ namespace Crow 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; @@ -1196,7 +1197,7 @@ namespace Crow 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 @@ -1208,9 +1209,9 @@ namespace Crow 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 @@ -1338,9 +1339,9 @@ namespace Crow #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; } @@ -1386,7 +1387,7 @@ namespace Crow allowDrop = value; NotifyValueChanged ("AllowDrop", allowDrop); } - } + } /// <summary> /// Semicolon separated list of accepted types as dropped widget. /// </summary> @@ -1443,17 +1444,17 @@ namespace Crow 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 ()); @@ -1470,7 +1471,7 @@ namespace Crow 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 @@ -1478,7 +1479,7 @@ namespace Crow 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 @@ -1489,7 +1490,7 @@ namespace Crow DbgLogger.StartEvent (DbgEvtType.GOClippingRegistration, this); parentRWLock.EnterReadLock (); - if (parent != null) { + if (parent != null) { parent.RegisterClip (LastPaintedSlot); parent.RegisterClip (Slot); }else { @@ -1513,7 +1514,7 @@ namespace Crow //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; @@ -1523,18 +1524,18 @@ namespace Crow 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 { @@ -1551,7 +1552,7 @@ namespace Crow } DbgLogger.StartEvent(DbgEvtType.GORegisterForGraphicUpdate, this); - IsDirty = true; + IsDirty = true; if (Width.IsFit || Height.IsFit) RegisterForLayouting (LayoutingType.Sizing); else @@ -1579,7 +1580,7 @@ namespace Crow /// 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) @@ -1597,7 +1598,7 @@ namespace Crow return lt == LayoutingType.Width ? contentSize.Width + 2 * margin : contentSize.Height + 2 * margin; } finally { - DbgLogger.EndEvent(DbgEvtType.GOMeasure); + DbgLogger.EndEvent(DbgEvtType.GOMeasure); } } @@ -1614,14 +1615,14 @@ namespace Crow } 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) @@ -1630,7 +1631,7 @@ namespace Crow return p.Width.IsFit; } if (!Height.IsRelativeToParent) - return false; + return false; while (p.Height.IsRelativeToParent) { p = p.Parent as Widget; if (p == null) @@ -1646,10 +1647,10 @@ namespace Crow /// 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) { @@ -1657,7 +1658,7 @@ namespace Crow return; } - parentRWLock.EnterReadLock (); + parentRWLock.EnterReadLock (); try { if (Parent == null) @@ -1666,14 +1667,14 @@ namespace Crow 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); @@ -1694,7 +1695,7 @@ namespace Crow RequiredLayoutings |= layoutType; } finally { - layoutMutex.ExitWriteLock (); + layoutMutex.ExitWriteLock (); } DbgLogger.StartEvent (DbgEvtType.GOLockLayouting, this); @@ -1760,7 +1761,7 @@ namespace Crow if (left == 0) { if (Parent.RequiredLayoutings.HasFlag (LayoutingType.Width) || - RequiredLayoutings.HasFlag (LayoutingType.Width)) + RequiredLayoutings.HasFlag (LayoutingType.Width)) return false; switch (horizontalAlignment) { @@ -1768,10 +1769,10 @@ namespace Crow 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 @@ -1790,7 +1791,7 @@ namespace Crow if (top == 0) { if (Parent.RequiredLayoutings.HasFlag (LayoutingType.Height) || - RequiredLayoutings.HasFlag (LayoutingType.Height)) + RequiredLayoutings.HasFlag (LayoutingType.Height)) return false; switch (verticalAlignment) { @@ -1798,10 +1799,10 @@ namespace Crow 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 @@ -1825,19 +1826,19 @@ namespace Crow } 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; @@ -1859,9 +1860,9 @@ namespace Crow } 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; @@ -1871,7 +1872,7 @@ namespace Crow Slot.Height = minimumSize.Height; else if (maximumSize.Height > 0 && Slot.Height > maximumSize.Height) Slot.Height = maximumSize.Height; - + } else Slot.Height = 0; @@ -1906,7 +1907,7 @@ namespace Crow #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); @@ -1947,12 +1948,12 @@ namespace Crow 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); @@ -1960,18 +1961,18 @@ namespace Crow 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 @@ -1996,13 +1997,13 @@ namespace Crow #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) { @@ -2010,8 +2011,8 @@ namespace Crow 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 (); @@ -2027,7 +2028,7 @@ namespace Crow if (!IsEnabled) paintDisabled (ctx, rb); - } + } LastPaintedSlot = Slot; //} @@ -2044,7 +2045,7 @@ namespace Crow } #endregion - #region Keyboard handling + #region Keyboard handling public virtual void onKeyDown(object sender, KeyEventArgs e){ if (KeyDown != null) KeyDown.Invoke (this, e); @@ -2063,7 +2064,7 @@ namespace Crow else if (!e.Handled) FocusParent?.onKeyPress (sender, e); } - #endregion + #endregion #region Mouse handling /// <summary> @@ -2081,7 +2082,7 @@ namespace Crow 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); @@ -2091,7 +2092,7 @@ namespace Crow 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)) @@ -2100,17 +2101,17 @@ namespace Crow } 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); } @@ -2171,7 +2172,7 @@ namespace Crow /// <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); @@ -2203,14 +2204,14 @@ namespace Crow 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){ @@ -2256,7 +2257,7 @@ namespace Crow string tmp =""; if (Parent != null) - tmp = Parent.ToString () + tmp; + tmp = Parent.ToString () + tmp; return string.IsNullOrEmpty(Name) ? tmp + "." + LogName : tmp + "." + Name; //#endif } @@ -2264,7 +2265,7 @@ namespace Crow /// Checks to handle when widget is removed from the visible graphic tree /// </summary> void unshownPostActions () { - IsDirty = true; + IsDirty = true; /*if (parent is Widget p) p.RegisterForGraphicUpdate(); @@ -2278,7 +2279,7 @@ namespace Crow { Debug.WriteLine($"[ERR]:unshownPostActions:{e}"); } - + /*if (IFace.ActiveWidget != null) { if (IsActive) { @@ -2304,7 +2305,7 @@ namespace Crow IFace.OnMouseMove (IFace.MousePosition.X, IFace.MousePosition.Y); } } - + /*Slot = default; try { @@ -2313,7 +2314,7 @@ namespace Crow if (LastSlots.Height > 0) OnLayoutChanges (LayoutingType.Height); OnLayoutChanges (LayoutingType.X); - OnLayoutChanges (LayoutingType.Y); + OnLayoutChanges (LayoutingType.Y); } catch (System.Exception ex) { @@ -2321,7 +2322,8 @@ namespace Crow } LastSlots = default; LastPaintedSlot = default;*/ - //Slot = LastSlots = default; + //Slot = LastSlots = LastPaintedSlot = default; + Slot = LastPaintedSlot = default; } } } diff --git a/Crow/src/Widgets/Window.cs b/Crow/src/Widgets/Window.cs index 6540a305..a028c7d7 100644 --- a/Crow/src/Widgets/Window.cs +++ b/Crow/src/Widgets/Window.cs @@ -172,7 +172,6 @@ namespace Crow 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); } diff --git a/Directory.Build.props b/Directory.Build.props index b91129b5..81510eed 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,7 @@ <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 @@ -18,7 +18,7 @@ <CrowDebugLogEnabled>false</CrowDebugLogEnabled> <!-- Collect several statistics on widgets--> - <CrowDebugStatsEnabled>true</CrowDebugStatsEnabled> + <CrowDebugStatsEnabled>false</CrowDebugStatsEnabled> <!-- Used only by CrowIDE and CrowEdit--> <CrowDesignModeEnabled>false</CrowDesignModeEnabled> diff --git a/Samples/common/src/Editor.cs b/Samples/common/src/Editor.cs index 22418f31..c093d345 100644 --- a/Samples/common/src/Editor.cs +++ b/Samples/common/src/Editor.cs @@ -155,7 +155,7 @@ namespace Crow 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}}' @@ -163,7 +163,7 @@ namespace Crow <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}'> @@ -172,7 +172,7 @@ namespace Crow <Label Text='{Name}' HorizontalAlignment='Left' /> </HorizontalStack> </ListItem> - </ItemTemplate> + </ItemTemplate> <ItemTemplate DataType='Colors'> <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left' Selected = '{Background=${ControlHighlight}}' diff --git a/Samples/common/ui/Interfaces/Experimental/testGrid.crow b/Samples/common/ui/Interfaces/Experimental/testGrid.crow new file mode 100644 index 00000000..1385acc4 --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/testGrid.crow @@ -0,0 +1,6 @@ +<Grid ColumnCount="2" RowCount="2"> + <Label/> + <Label/> + <Label/> + <Label/> +</Grid>
\ No newline at end of file |