diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2025-02-27 01:16:26 +0100 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2025-02-27 01:16:26 +0100 |
| commit | 9076776696efe1300efd339c999dfe49a62eb7ee (patch) | |
| tree | 1cd2b0ee833c6971b6e51d2d3fee100f387f0478 | |
| parent | fd4ca65c552512784f7a077aa34f3e34c0a79122 (diff) | |
wip
71 files changed, 1293 insertions, 632 deletions
diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..adb261b8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,225 @@ +--- +Language: CSharp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseTab: Never +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + diff --git a/Backends/CairoBackend/Crow.CairoBackend.csproj b/Backends/CairoBackend/Crow.CairoBackend.csproj index 50563bd7..6b15a45e 100644 --- a/Backends/CairoBackend/Crow.CairoBackend.csproj +++ b/Backends/CairoBackend/Crow.CairoBackend.csproj @@ -3,7 +3,7 @@ <PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> - <AssemblyVersion>1.2.0</AssemblyVersion> + <AssemblyVersion>1.2.1</AssemblyVersion> <PackageVersion>$(AssemblyVersion)-beta</PackageVersion> <Title>C.R.O.W Cairo Backend</Title> diff --git a/Backends/CairoBackend/src/Context.cs b/Backends/CairoBackend/src/Context.cs index f9af1bf1..4472f650 100644 --- a/Backends/CairoBackend/src/Context.cs +++ b/Backends/CairoBackend/src/Context.cs @@ -266,8 +266,12 @@ namespace Crow.CairoBackend => Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); public void Rectangle (PointD p, double width, double height) => Rectangle (p.X, p.Y, width, height); - public void Rectangle (double x, double y, double width, double height) - => NativeMethods.cairo_rectangle (handle, x, y, width, height); + public void Rectangle (double x, double y, double width, double height) { + if (width > 0 && height > 0) + NativeMethods.cairo_rectangle (handle, x, y, width, height); + else + System.Diagnostics.Debug.WriteLine("cairo: invalid rectangle"); + } public void ClosePath () => NativeMethods.cairo_close_path (handle); public Path CopyPath () => new Path (NativeMethods.cairo_copy_path (handle)); public Path CopyPathFlat () => new Path (NativeMethods.cairo_copy_path_flat (handle)); diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj index f73c69e8..9fdc56e0 100644 --- a/Crow/Crow.csproj +++ b/Crow/Crow.csproj @@ -67,7 +67,7 @@ <EmbeddedResource Include="Cursors\*.*"> <LogicalName>Crow.Cursors.%(Filename)</LogicalName> </EmbeddedResource> - <Compile Include="Properties\AssemblyInfo.cs" /> + <!--<Compile Include="Properties\AssemblyInfo.cs" />--> <Compile Remove="src\Widgets\ColorPicker2.cs" /> </ItemGroup> @@ -77,4 +77,10 @@ <ItemGroup> <ProjectReference Include="..\Drawing2D\Drawing2D.csproj" /> </ItemGroup> + + <ItemGroup> + <AssemblyAttribute Include="Crow.CrowAssemblyPriority"> + <_Parameter1>1000</_Parameter1> + </AssemblyAttribute> + </ItemGroup> </Project> diff --git a/Crow/Default.style b/Crow/Default.style index 98c5276b..473f4070 100644 --- a/Crow/Default.style +++ b/Crow/Default.style @@ -265,7 +265,7 @@ HSVSpinner { } TxtInFileDialog { Margin = "1"; - Font = "droid, 12"; + Font = "mono, 12"; } CheckBoxAlt { Template= "#Crow.CheckBox2.template"; @@ -305,6 +305,9 @@ HScrollBar { Width = "Inherit"; Orientation = "Horizontal"; } +ScrollingListBox { + Template= "#Crow.ScrollingListBox.template"; +} EnumSelector { Width = "Fit"; Height = "Fit"; diff --git a/Crow/Properties/AssemblyInfo.cs b/Crow/Properties/AssemblyInfo.cs deleted file mode 100644 index d8646524..00000000 --- a/Crow/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com> -// -// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -[assembly: Crow.Crow ] - diff --git a/Crow/src/CrowAssemblyAttribute.cs b/Crow/src/CrowAssemblyAttribute.cs index 647a84fe..d09e348b 100644 --- a/Crow/src/CrowAssemblyAttribute.cs +++ b/Crow/src/CrowAssemblyAttribute.cs @@ -2,16 +2,22 @@ // // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; -namespace Crow +namespace Crow { +/// <summary> +/// Add this attribute to an assembly to have it search for Crow ressources (.style, images, templates,...) +/// </summary> +/// <remarks> +/// By default, only the entry assembly and the crow assembly will be searched for resources. +/// </remarks> +[AttributeUsage (AttributeTargets.Assembly)] + +public class CrowAssemblyPriority : Attribute { - /// <summary> - /// Add this attribute to an assembly to have it search for Crow ressources (.style, images, templates,...) - /// </summary> - /// <remarks> - /// By default, only the entry assembly and the crow assembly will be searched for resources. - /// </remarks> - [AttributeUsage (AttributeTargets.Assembly)] - public class CrowAttribute : Attribute - { + public int Priority = 1000; + public CrowAssemblyPriority(string priority) { + if (int.TryParse(priority, out int pri)) { + Priority = pri; + } } } +} diff --git a/Crow/src/DebugUtils/DebugLogger.cs b/Crow/src/DebugUtils/DebugLogger.cs index c859fef9..f7078ed8 100644 --- a/Crow/src/DebugUtils/DebugLogger.cs +++ b/Crow/src/DebugUtils/DebugLogger.cs @@ -171,12 +171,23 @@ lock (logMutex) { if (!logevt (evtType)) return; - lock (logMutex) { - chrono.Stop (); - DbgEvent evt = addEventInternal (evtType, data); - evt.Message = message; - chrono.Start (); - } + Monitor.Enter (logMutex); + chrono.Stop (); + DbgEvent evt = addEventInternal (evtType, data); + evt.Message = message; + chrono.Start (); + Monitor.Exit(logMutex); + + if (ConsoleOutput) { + if (evt.type.HasFlag (DbgEvtType.Error)) { + Console.ForegroundColor = ConsoleColor.Red; + } + if (evt is DbgWidgetEvent we) { + Console.WriteLine ($"{evt.Print()} {Widget.GraphicObjects[we.InstanceIndex]}"); + } else + Console.WriteLine ($"{evt.Print()}"); + Console.ResetColor (); + } #endif } @@ -202,16 +213,7 @@ lock (logMutex) { else evt = new DbgEvent (chrono.ElapsedTicks, evtType); - if (ConsoleOutput) { - if (evt.type.HasFlag (DbgEvtType.Error)) { - Console.ForegroundColor = ConsoleColor.Red; - } - if (evt is DbgWidgetEvent we) - Console.WriteLine ($"{evt.Print()} {Widget.GraphicObjects[we.InstanceIndex]}"); - else - Console.WriteLine ($"{evt.Print()}"); - Console.ResetColor (); - } else + if (!ConsoleOutput) curEventList.Add (evt); return evt; } @@ -362,7 +364,6 @@ lock (logMutex) { }*/ } startedEvents.Pop(); - } } } diff --git a/Crow/src/ExtensionsMethods.cs b/Crow/src/ExtensionsMethods.cs index 41c31a64..ed226b8a 100644 --- a/Crow/src/ExtensionsMethods.cs +++ b/Crow/src/ExtensionsMethods.cs @@ -15,6 +15,17 @@ namespace Crow { public static class ExtensionsMethods { + #region CrowAssemblyPriority + internal static bool TryGetCrowAssemblyPriority(this Assembly a, out int priority) { + priority = -1; + if (a.GetCustomAttributes(typeof(CrowAssemblyPriority)).FirstOrDefault() is CrowAssemblyPriority cap) { + priority = cap.Priority; + return true; + } + return false; + } + #endregion + #region Cairo extensions public static void Rectangle(this IContext ctx, Rectangle r, double stroke = 0.0) diff --git a/Crow/src/Fill/BmpPicture.cs b/Crow/src/Fill/BmpPicture.cs index 7cf8983c..b4ad651e 100644 --- a/Crow/src/Fill/BmpPicture.cs +++ b/Crow/src/Fill/BmpPicture.cs @@ -33,6 +33,7 @@ namespace Crow /// load the image for rendering from the path given as argument /// </summary> public override void load (Interface iFace) { + DbgLogger.AddEventWithMsg(DbgEvtType.Ressources, $"BMPPicture.load:{Path}"); if (iFace.sharedPictures.ContainsKey (Path)) { sharedPicture sp = iFace.sharedPictures[Path]; image = (byte[])sp.Data; @@ -45,106 +46,24 @@ namespace Crow iFace.sharedPictures[Path] = new sharedPicture (image, Dimensions); } } - - //load image via System.Drawing.Bitmap, cairo load png only - /*void loadBitmap (System.Drawing.Bitmap bitmap) - { - if (bitmap == null) - return; - - System.Drawing.Imaging.BitmapData data = bitmap.LockBits - (new System.Drawing.Rectangle (0, 0, bitmap.Width, bitmap.Height), - System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - - Dimensions = new Size (bitmap.Width, bitmap.Height); - - int stride = data.Stride; - int bitmapSize = Math.Abs (data.Stride) * bitmap.Height; - - image = new byte[bitmapSize]; - System.Runtime.InteropServices.Marshal.Copy (data.Scan0, image, 0, bitmapSize); - - bitmap.UnlockBits (data); - }*/ + public override void LoadFromStream (Interface iFace, Stream stream) { + DbgLogger.AddEventWithMsg(DbgEvtType.Ressources, $"BMPPicture.LoadFromStream:{Path}"); + image = iFace.Backend.LoadBitmap (stream, out Size dimensions); + Dimensions = dimensions; + iFace.sharedPictures[Path] = new sharedPicture (image, Dimensions); + } #region implemented abstract members of Fill public override bool IsLoaded => image != null; - public override void SetAsSource (Interface iFace, IContext ctx, Rectangle bounds = default(Rectangle)) - { - if (image == null) - load (iFace); - - float widthRatio = 1f; - float heightRatio = 1f; - - if (Scaled){ - widthRatio = (float)bounds.Width / Dimensions.Width; - heightRatio = (float)bounds.Height / Dimensions.Height; - } - - if (KeepProportions) { - if (widthRatio < heightRatio) - heightRatio = widthRatio; - else - widthRatio = heightRatio; - } - - using (ISurface tmp = iFace.Backend.CreateSurface (bounds.Width, bounds.Height)) { - using (IContext gr = iFace.Backend.CreateContext (tmp)) { - gr.Translate (bounds.Left, bounds.Top); - gr.Scale (widthRatio, heightRatio); - gr.Translate ((bounds.Width/widthRatio - Dimensions.Width)/2, (bounds.Height/heightRatio - Dimensions.Height)/2); - - using (ISurface imgSurf = iFace.Backend.CreateSurface (image, Dimensions.Width, Dimensions.Height)) { - gr.SetSource (imgSurf, 0,0); - gr.Paint (); - } - } - ctx.SetSource (tmp); - } - } #endregion - /// <summary> - /// paint the image in the rectangle given in arguments according - /// to the Scale and keepProportion parameters. - /// </summary> - /// <param name="gr">drawing Backend context</param> - /// <param name="rect">bounds of the target surface to paint</param> - /// <param name="subPart">used for svg only</param> - public override void Paint (Interface iFace, IContext gr, Rectangle rect, string subPart = "") - { - if (image == null) - load (iFace); - - double widthRatio = 1; - double heightRatio = 1; - - if (Scaled){ - widthRatio = (double)rect.Width / Dimensions.Width; - heightRatio = (double)rect.Height / Dimensions.Height; - } - - if (KeepProportions) { - if (widthRatio < heightRatio) - heightRatio = widthRatio; - else - widthRatio = heightRatio; - } - - gr.SaveTransformations (); - - gr.Translate (rect.Left,rect.Top); - gr.Scale (widthRatio, heightRatio); - gr.Translate ((rect.Width/widthRatio - Dimensions.Width)/2, (rect.Height/heightRatio - Dimensions.Height)/2); - + protected override void Render(Interface iFace, IContext gr, string subPart = "") + { using (ISurface imgSurf = iFace.Backend.CreateSurface (image, Dimensions.Width, Dimensions.Height)) { gr.SetSource (imgSurf, 0,0); gr.Paint (); } - - gr.RestoreTransformations (); - } + } } } diff --git a/Crow/src/Fill/Picture.cs b/Crow/src/Fill/Picture.cs index b5655c1a..a2c67613 100644 --- a/Crow/src/Fill/Picture.cs +++ b/Crow/src/Fill/Picture.cs @@ -8,6 +8,8 @@ using System.IO; using System.Collections.Generic; using Drawing2D; +using System.Globalization; +using Crow.DebugLogger; namespace Crow { @@ -66,16 +68,70 @@ namespace Crow } #endregion + void init(Interface iFace, ref Rectangle rect, out float widthRatio, out float heightRatio) { + if (!IsLoaded) + load (iFace); + + widthRatio = 1f; + heightRatio = 1f; + + if (Scaled) { + widthRatio = (float)rect.Width / Dimensions.Width; + heightRatio = (float)rect.Height / Dimensions.Height; + if (KeepProportions) { + if (widthRatio < heightRatio) + heightRatio = widthRatio; + else + widthRatio = heightRatio; + } + } + } + /// <summary> - /// abstract method to paint the image in the rectangle given in arguments according + /// paint the picture in the rectangle given in arguments according /// to the Scale and keepProportion parameters. /// </summary> /// <param name="gr">drawing Backend context</param> - /// <param name="rect">bounds of the target surface to paint</param> - /// <param name="subPart">used for svg only</param> - public abstract void Paint(Interface iFace, IContext ctx, Rectangle rect, string subPart = ""); + /// <param name="bounds">bounds of the target surface to paint</param> + /// <param name="subPart">limit rendering to this coma separated list of svg part identified with their svg 'id' attribute.</param> + public void Paint (Interface iFace, IContext gr, Rectangle bounds, string subPart = "") + { + DbgLogger.AddEventWithMsg(DbgEvtType.Ressources, $"{Path}[Picture.Paint:]"); + + init(iFace, ref bounds, out float widthRatio, out float heightRatio); + + gr.SaveTransformations (); + + gr.Translate (bounds.Left,bounds.Top); + gr.Scale (widthRatio, heightRatio); + gr.Translate (((float)bounds.Width/widthRatio - Dimensions.Width)/2f, ((float)bounds.Height/heightRatio - Dimensions.Height)/2f); + + Render(iFace, gr, subPart); + + gr.RestoreTransformations (); + } + public override void SetAsSource (Interface iFace, IContext ctx, Rectangle bounds = default(Rectangle)) + { + DbgLogger.AddEventWithMsg(DbgEvtType.Ressources, $"{Path} [Picture.SetAsSource]"); + + init(iFace, ref bounds, out float widthRatio, out float heightRatio); + + using (ISurface tmp = iFace.Backend.CreateSurface (bounds.Width, bounds.Height)) { + using (IContext gr = iFace.Backend.CreateContext (tmp)) { + gr.Translate (bounds.Left, bounds.Top); + gr.Scale (widthRatio, heightRatio); + gr.Translate ((bounds.Width/widthRatio - Dimensions.Width)/2, (bounds.Height/heightRatio - Dimensions.Height)/2); + + Render(iFace, gr); + } + ctx.SetSource (tmp); + } + } + //final rendering on a scaled and configured context + protected abstract void Render(Interface iFace, IContext gr, string subPart = ""); public abstract bool IsLoaded { get; } public abstract void load (Interface iface); + public abstract void LoadFromStream (Interface iface, Stream stream); #region Operators public static implicit operator Picture(string path) => Parse (path) as Picture; public static implicit operator string(Picture _pic) => _pic == null ? null : _pic.Path; @@ -88,6 +144,8 @@ namespace Crow Picture _pic = null; + DbgLogger.AddEventWithMsg(DbgEvtType.Ressources, $"Picture.parse:{path}"); + if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture)) _pic = new SvgPicture (path); else diff --git a/Crow/src/Fill/SvgPicture.cs b/Crow/src/Fill/SvgPicture.cs index e2c73bbd..0fe954af 100644 --- a/Crow/src/Fill/SvgPicture.cs +++ b/Crow/src/Fill/SvgPicture.cs @@ -31,6 +31,7 @@ namespace Crow public override void load (Interface iFace) { + DbgLogger.AddEventWithMsg(DbgEvtType.Ressources, $"SVGPicture.load:{Path}"); if (iFace.sharedPictures.ContainsKey (Path)) { sharedPicture sp = iFace.sharedPictures [Path]; hSVG = (ISvgHandle)sp.Data; @@ -42,8 +43,14 @@ namespace Crow Dimensions = hSVG.Dimensions; iFace.sharedPictures [Path] = new sharedPicture (hSVG, Dimensions); } - + public override void LoadFromStream (Interface iFace, Stream stream) { + DbgLogger.AddEventWithMsg(DbgEvtType.Ressources, $"SVGPicture.LoadFromStream:{Path}"); + hSVG = iFace.Backend.LoadSvg (stream); + Dimensions = hSVG.Dimensions; + iFace.sharedPictures [Path] = new sharedPicture (hSVG, Dimensions); + } public void LoadSvgFragment (Interface iface, string fragment) { + DbgLogger.AddEventWithMsg(DbgEvtType.Ressources, $"SVGPicture.LoadSvgFragment:{fragment}"); hSVG = iface.Backend.LoadSvg (fragment); Dimensions = hSVG.Dimensions; } @@ -52,7 +59,7 @@ namespace Crow public override bool IsLoaded => hSVG != null; public override void SetAsSource (Interface iFace, IContext ctx, Rectangle bounds = default(Rectangle)) { - if (hSVG == null) + if (!IsLoaded) load (iFace); float widthRatio = 1f; @@ -82,38 +89,9 @@ namespace Crow } #endregion - /// <summary> - /// paint the image in the rectangle given in arguments according - /// to the Scale and keepProportion parameters. - /// </summary> - /// <param name="gr">drawing Backend context</param> - /// <param name="rect">bounds of the target surface to paint</param> - /// <param name="subPart">limit rendering to this coma separated list of svg part identified with their svg 'id' attribute.</param> - public override void Paint (Interface iFace, IContext gr, Rectangle rect, string subPart = "") - { - if (hSVG == null) - load (iFace); - - float widthRatio = 1f; - float heightRatio = 1f; - - if (Scaled) { - widthRatio = (float)rect.Width / Dimensions.Width; - heightRatio = (float)rect.Height / Dimensions.Height; - } - if (KeepProportions) { - if (widthRatio < heightRatio) - heightRatio = widthRatio; - else - widthRatio = heightRatio; - } - - gr.Save (); - - gr.Translate (rect.Left,rect.Top); - gr.Scale (widthRatio, heightRatio); - gr.Translate (((float)rect.Width/widthRatio - Dimensions.Width)/2f, ((float)rect.Height/heightRatio - Dimensions.Height)/2f); + protected override void Render(Interface iFace, IContext gr, string subPart = "") + { if (string.IsNullOrEmpty (subPart)) hSVG.Render (gr); else { @@ -121,9 +99,8 @@ namespace Crow foreach (string p in parts) hSVG.Render (gr, "#" + subPart); } - - gr.Restore (); - } - } + + } + } } diff --git a/Crow/src/IML/CompilerServices.cs b/Crow/src/IML/CompilerServices.cs index ba6e2935..9ddc43be 100644 --- a/Crow/src/IML/CompilerServices.cs +++ b/Crow/src/IML/CompilerServices.cs @@ -392,7 +392,7 @@ namespace Crow.IML if (knownExtMethods.ContainsKey (key)) return knownExtMethods [key]; - //System.Diagnostics.Console.WriteLine ($"*** search extension method: {t};{methodName} => key={key}"); + DbgLogger.AddEvent (DbgEvtType.Binding, $"[CompilerServices.SearchExtMethod] search extension method: {t};{methodName} => key={key}"); MethodInfo mi = null; if (!TryGetExtensionMethods (Assembly.GetEntryAssembly (), t, methodName, out mi)) { @@ -411,7 +411,7 @@ namespace Crow.IML return mi; } } catch (Exception e) {//added this catch for CrowEdit, ext method should be search with appropriate LoadContext. - Debug.WriteLine ($"[CompilerServices.SearchExtMethod]{e}"); + DbgLogger.AddEvent (DbgEvtType.Binding | DbgEvtType.Error, $"[CompilerServices.SearchExtMethod]{e}"); } return null; } @@ -421,18 +421,32 @@ namespace Crow.IML foundMI = null; if (assembly == null) return false; + DbgLogger.AddEvent (DbgEvtType.Binding, $"[CompilerServices.TryGetExtensionMethods] search in {assembly.FullName}"); foreach (Type t in assembly.GetExportedTypes().Where (ty => ty.IsDefined (typeof (ExtensionAttribute), false))) { + DbgLogger.AddEvent (DbgEvtType.Binding, $"[CompilerServices.TryGetExtensionMethods] search in type: {t.FullName}"); foreach (MethodInfo mi in t.GetMethods (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Where (m=> m.Name == methodName && m.IsDefined (typeof (ExtensionAttribute), false) && m.GetParameters ().Length > 0)) { + DbgLogger.AddEvent (DbgEvtType.Binding, $"[CompilerServices.TryGetExtensionMethods] testing method: {mi.Name} extendedType:{extendedType}"); Type curType = extendedType; while (curType != null) { - if (mi.GetParameters () [0].ParameterType == curType) { + Type firstParamType = mi.GetParameters () [0].ParameterType; + if (firstParamType == curType) { + DbgLogger.AddEvent (DbgEvtType.Binding, $"[CompilerServices.TryGetExtensionMethods] Found for {curType}"); foundMI = mi; return true; } + if (firstParamType.IsInterface) { + foreach (Type ifaceType in curType.GetInterfaces()) { + if (firstParamType == ifaceType) { + DbgLogger.AddEvent (DbgEvtType.Binding, $"[CompilerServices.TryGetExtensionMethods] Found interface {ifaceType} in {curType}"); + foundMI = mi; + return true; + } + } + } curType = curType.BaseType; } } diff --git a/Crow/src/IML/Instantiator.cs b/Crow/src/IML/Instantiator.cs index e338e714..69159830 100644 --- a/Crow/src/IML/Instantiator.cs +++ b/Crow/src/IML/Instantiator.cs @@ -828,11 +828,11 @@ namespace Crow.IML { il.MarkLabel (cancel); //#if DEBUG_BINDING //TODO: try to print datasource type in the error message - il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' NOT FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name)); + il.EmitWriteLine ($"[{dm.Name}] Handler method '{bindingDef.TargetMember}' for '{sourceEvent.Name}' NOT FOUND in new dataSource"); //#endif il.MarkLabel (finish); #if DEBUG_BINDING - il.EmitWriteLine (string.Format ("Handler method '{0}' for '{1}' FOUND in new dataSource", bindingDef.TargetMember, sourceEvent.Name)); + il.EmitWriteLine ($"[{dm.Name}] Handler method '{bindingDef.TargetMember}' for '{sourceEvent.Name}' FOUND in new dataSource"); #endif il.Emit (OpCodes.Ret); @@ -1525,7 +1525,9 @@ namespace Crow.IML { foreach (string m in destMember.Split('.')) { MemberInfo miDest = curType.GetMember (m).FirstOrDefault (); if (miDest == null) { - Console.WriteLine ($"Member '{destMember}' not found in new DataSource '{dest}' of '{orig}'"); +#if DEBUG_BINDING + Console.WriteLine ($"[ITOR][dataSourceReverseBinding] {delName} Member '{destMember}' not found in new DataSource '{dest}' of '{orig}'"); +#endif return; } miDests.Add (miDest); diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index 09407be4..e865739e 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -20,6 +20,9 @@ using Glfw; using Path = System.IO.Path; using Drawing2D; +using System.Runtime.Loader; +using System.Net.Http; +using System.Threading.Tasks; namespace Crow { @@ -60,6 +63,8 @@ namespace Crow /// the 'UpdateFrame' method in the 'Run' cycle and may be overriden. /// </summary> public static int POLLING_INTERVAL = 1; + /// <summary>Maximum total layoutings</summary> + public static long MAX_LAYOUTINGS_COUNT = 200000; /// <summary>Crow configuration root path</summary> public static string CROW_CONFIG_ROOT; /// <summary>If true, mouse focus is given when mouse is over control</summary> @@ -97,8 +102,6 @@ namespace Crow /// </summary> //protected static Interface CurrentInterface; #endregion - - internal static List<Assembly> crowAssemblies = new List<Assembly> (); /// <summary> /// Add Assembly that may contains CROW ui ressources like custom widget classes, IML, images, ... /// Styling fond in those assemblies are automatically loaded on addition; @@ -126,6 +129,7 @@ namespace Crow init_internal (); } } + internal static List<Assembly> crowAssemblies; static IntPtr resolveUnmanaged(Assembly assembly, String libraryName) { try { @@ -160,28 +164,35 @@ namespace Crow /// backends are search where the main crow assembly is. /// </summary> public static string BackendsDirectory = null; - protected static Type getBackendType (IEnumerable<Type> backendTypes) { + protected static Type getBackend (IEnumerable<Type> backendTypes) { if (backendTypes == null) return null; + Type backend = null; switch (PreferedBackendType) { case BackendType.Default: - return backendTypes.FirstOrDefault(be => be.Name == "DefaultBackend"); + backend = backendTypes.FirstOrDefault(be => be.Name == "DefaultBackend"); + break; case BackendType.Egl: - return backendTypes.FirstOrDefault(be => be.Name == "EglBackend"); + backend = backendTypes.FirstOrDefault(be => be.Name == "EglBackend"); + break; case BackendType.Vulkan: - return backendTypes.FirstOrDefault(be => be.Name == "VulkanBackend"); + backend = backendTypes.FirstOrDefault(be => be.Name == "VulkanBackend"); + break; case BackendType.Gl: - return backendTypes.FirstOrDefault(be => be.Name == "GlBackend"); + backend = backendTypes.FirstOrDefault(be => be.Name == "GlBackend"); + break; default: - return backendTypes.FirstOrDefault(); + backend = backendTypes.FirstOrDefault(); + break; } + return backend ?? backendTypes.FirstOrDefault(); } - protected static bool tryFindBackendType (out Type backendType) { + protected static bool tryFindBackend (out Type backendType) { backendType = default; //search loaded assemblies System.Runtime.Loader.AssemblyLoadContext ldCtx = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()); foreach (Assembly a in ldCtx.Assemblies.Where (asb => backends.Contains (asb.GetName ().Name))) { - backendType = getBackendType (a.ExportedTypes?.Where (e=>e.IsSubclassOf(typeof(CrowBackend)) && !e.IsAbstract)); + backendType = getBackend (a.ExportedTypes?.Where (e=>e.IsSubclassOf(typeof(CrowBackend)) && !e.IsAbstract)); if (backendType != null) return true; } @@ -194,7 +205,7 @@ namespace Crow string bPath = Path.Combine (bp,$"Crow.{b}.dll"); if (File.Exists (bPath)) { Assembly a = ldCtx.LoadFromAssemblyPath (bPath); - backendType = getBackendType (a.ExportedTypes?.Where (e=>e.IsSubclassOf(typeof(CrowBackend)) && !e.IsAbstract)); + backendType = getBackend (a.ExportedTypes?.Where (e=>e.IsSubclassOf(typeof(CrowBackend)) && !e.IsAbstract)); return backendType != null; } } @@ -205,7 +216,8 @@ namespace Crow #region CTOR static Interface () { - System.Runtime.Loader.AssemblyLoadContext ldCtx = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()); + Assembly crowAssembly = Assembly.GetExecutingAssembly(); + System.Runtime.Loader.AssemblyLoadContext ldCtx = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(crowAssembly); ldCtx.ResolvingUnmanagedDll += resolveUnmanaged; CROW_CONFIG_ROOT = @@ -216,44 +228,14 @@ namespace Crow if (!Directory.Exists (CROW_CONFIG_ROOT)) Directory.CreateDirectory (CROW_CONFIG_ROOT); - } - /// <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) - return; - preloadCrowAssemblies (value); - } - } - static void preloadCrowAssemblies (string [] crowAssemblyNames) { - //ensure all assemblies are loaded, because IML could contains classes not instanciated in source - /*Assembly ea = Assembly.GetEntryAssembly (); - System.IO.FileStream[] files = ea.GetFiles (); - foreach (AssemblyName an in ea.GetReferencedAssemblies()) { - try { - Assembly a = Assembly.ReflectionOnlyLoad (an.Name); - if (a == Assembly.GetExecutingAssembly ()) - continue; - if (a.GetCustomAttribute (typeof (CrowAttribute)) != null) - crowAssemblies.Add (a); - } catch { - - } - }*/ - foreach (string assemblyName in crowAssemblyNames) { - try { - crowAssemblies.Add (Assembly.Load (assemblyName)); - } catch (Exception ex) { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine ($"Unable to preload CrowAssembly: {assemblyName}: {ex}"); - Console.ResetColor(); + SortedDictionary<int, Assembly> assemblies = new SortedDictionary<int, Assembly>(); + AssemblyLoadContext ctx = AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()); + foreach (Assembly assembly in ctx.Assemblies) { + if (assembly != crowAssembly && assembly.TryGetCrowAssemblyPriority(out int priority)) { + assemblies.Add(priority, assembly); } } - + crowAssemblies = assemblies.Values.Reverse().ToList(); } /// <summary> /// Create a new Crow Interface by providing an existing valid GLFW window handle. @@ -440,7 +422,7 @@ namespace Crow } protected virtual void initBackend () { - if (!tryFindBackendType (out Type backendType)) + if (!tryFindBackend (out Type backendType)) throw new Exception ("No backend found."); backend = (CrowBackend)Activator.CreateInstance (backendType, new object[] {clientRectangle.Width, clientRectangle.Height, hWin}); hWin = backend.hWin; @@ -464,14 +446,12 @@ namespace Crow knownCrowWidgetTypes.Add (typeName, t); return t; } - //TODO:LoadContext may now be used there!!! foreach (Type expT in Assembly.GetEntryAssembly ().GetExportedTypes ()) { if (expT.Name != typeName) continue; knownCrowWidgetTypes.Add (typeName, expT); return expT; } - foreach (Assembly a in Interface.crowAssemblies) { foreach (Type expT in a.GetExportedTypes ()) { if (expT.Name != typeName) @@ -489,7 +469,7 @@ namespace Crow if (knownExtMethods.ContainsKey (key)) return knownExtMethods [key]; - //System.Diagnostics.Debug.WriteLine ($"*** search extension method: {t};{methodName} => key={key}"); + Debug.WriteLine ($"[iface] search extension method: {t};{methodName} => key={key}"); MethodInfo mi = null; if (!CompilerServices.TryGetExtensionMethods (Assembly.GetEntryAssembly (), t, methodName, out mi)) { @@ -707,13 +687,6 @@ namespace Crow } #endif - - - - - - - #region DragAndDrop public bool DragAndDropInProgress => DragAndDropOperation != null; public Widget DropTarget => DragAndDropOperation?.DropTarget; @@ -725,7 +698,7 @@ namespace Crow public void ClearDragImage () { lock (UpdateMutex) { if (DragImage == null) - return; + return; clipping.UnionRectangle (lastDragImageBounds); DragImage.Dispose(); DragImage = null; @@ -925,16 +898,19 @@ namespace Crow string resId = path.Substring (1); if (tryFindResource (Assembly.GetEntryAssembly (), resId, out stream)) return stream; - string[] assemblyNames = resId.Split ('.'); + /*string[] assemblyNames = resId.Split ('.'); if (AppDomain.CurrentDomain.GetAssemblies ().FirstOrDefault (aa => aa.GetName ().Name == assemblyNames[0]).TryGetResource (resId, out stream)) return stream; if (assemblyNames.Length > 3) if (tryFindResource (AppDomain.CurrentDomain.GetAssemblies () .FirstOrDefault (aa => aa.GetName ().Name == $"{assemblyNames[0]}.{assemblyNames[1]}"), resId, out stream)) - return stream; + return stream;*/ foreach (Assembly ca in crowAssemblies) if (tryFindResource (ca, resId, out stream)) return stream; + if (tryFindResource (Assembly.GetExecutingAssembly (), resId, out stream)) + return stream; + throw new Exception ("Resource not found: " + path); } if (!File.Exists (path)) @@ -1151,6 +1127,13 @@ namespace Crow } else if (lastMouseDown.ElapsedMilliseconds > DEVICE_REPEAT_DELAY) mouseRepeatTimer.Start (); } + if (FocusedWidget != null && typeof(IEditableTextWidget).IsAssignableFrom(FocusedWidget.GetType())) { + if (blinkingCursor.ElapsedMilliseconds > TEXT_CURSOR_BLINK_FREQUENCY) { + blinkingCursor.Restart(); + drawTextCursor = !drawTextCursor; + FocusedWidget?.RegisterForRepaint(); + } + } if (!Monitor.TryEnter (UpdateMutex)) return; @@ -1171,7 +1154,7 @@ namespace Crow clipping.UnionRectangle(lastDragImageBounds); } - if (!clipping.IsEmpty || shouldDrawTextCursor) { + if (!clipping.IsEmpty) { ctx = Backend.PrepareUIFrame (ctx, clipping); processDrawing (ctx); Backend.FlushUIFrame (ctx); @@ -1198,10 +1181,14 @@ namespace Crow PerformanceMeasure.Begin (PerformanceMeasure.Kind.Layouting); try { DiscardQueue = new Queue<LayoutingQueueItem> (LayoutingQueue.Count); - while (LayoutingQueue.Count > 0) { + long totLayoutings = 0; + while (LayoutingQueue.Count > 0 && totLayoutings++ < MAX_LAYOUTINGS_COUNT) { LayoutingQueueItem lqi = LayoutingQueue.Dequeue (); lqi.ProcessLayouting (); } + if (totLayoutings == MAX_LAYOUTINGS_COUNT) { + DbgLogger.AddEvent(DbgEvtType.LayoutingLoopError); + } LayoutingQueue = DiscardQueue; } finally { PerformanceMeasure.End (PerformanceMeasure.Kind.Layouting); @@ -1259,6 +1246,16 @@ namespace Crow } if (lastDragImageBounds != DragImageBounds) { + /*ctx.LineWidth = 1; + ctx.SetSource(1,0,0,0.6); + ctx.Rectangle(DragImageBounds); + ctx.Stroke (); + ctx.SetSource(0,1,0,0.6); + ctx.Rectangle(lastDragImageBounds); + ctx.Stroke (); + ctx.Arc(lastDragImageBounds.X, lastDragImageBounds.Y, 5,0,Math.PI*2.0); + ctx.Fill ();*/ + DirtyRect += lastDragImageBounds; ctx.Save (); ctx.ResetClip (); @@ -1272,11 +1269,10 @@ namespace Crow #if DEBUG_CLIP_RECTANGLE ctx.LineWidth = 1; - ctx.SetSource(1,1,0,0.5); - for (int i = 0; i < clipping.NumRectangles; i++) - ctx.Rectangle(clipping.GetRectangle(i)); + ctx.SetSource(1,1,0,0.6); + for (int i = 0; i < clipping.NumRectangles; i++) + ctx.Rectangle(clipping.GetRectangle(i).Inflated(-1,-1)); ctx.Stroke (); - #endif clipping.Reset (); @@ -1285,8 +1281,6 @@ namespace Crow IsDirty = true; } - drawTextCursor (ctx); - debugHighlightFocus (ctx); DbgLogger.EndEvent (DbgEvtType.ProcessDrawing, true); @@ -1322,39 +1316,24 @@ namespace Crow /// Text cursor blinking frequency. /// </summary> public static long TEXT_CURSOR_BLINK_FREQUENCY = 400; - internal Rectangle? textCursor = null;//last printed cursor, used to clear it. - public bool forceTextCursor = true;//when true, cursor is printed even if blinkingCursor.elapsed is not reached. - Stopwatch blinkingCursor = Stopwatch.StartNew (); - void drawTextCursor (IContext ctx) { - if (forceTextCursor) { - if (FocusedWidget is IEditableTextWidget lab) { - if (lab.DrawCursor (ctx, out Rectangle c)) { - if (textCursor != null && c != textCursor.Value) - RegisterChildClip (textCursor.Value); - textCursor = c; - //MainSurface.Flush (); - } else if (textCursor != null) - RegisterChildClip (textCursor.Value); - } - blinkingCursor.Restart (); - forceTextCursor = false; - } else if (textCursor != null && blinkingCursor.ElapsedMilliseconds > TEXT_CURSOR_BLINK_FREQUENCY) { - RegisterChildClip (textCursor.Value); - textCursor = null; - blinkingCursor.Restart (); - } else if (FocusedWidget is IEditableTextWidget lab) { - if (blinkingCursor.ElapsedMilliseconds > TEXT_CURSOR_BLINK_FREQUENCY) { - if (lab.DrawCursor (ctx, out Rectangle c)) { - textCursor = c; - //MainSurface.Flush (); - blinkingCursor.Restart (); - } - } + + bool _drawTextCursor = true; + public bool drawTextCursor { + get => _drawTextCursor; + set { + if (_drawTextCursor == value) + return; + _drawTextCursor = value; + //Console.WriteLine($"draw cursor: {_drawTextCursor}"); } } + + public void forceTextCursor () { + drawTextCursor = true; + blinkingCursor.Restart(); + } + Stopwatch blinkingCursor = Stopwatch.StartNew (); #endregion - bool shouldDrawTextCursor => forceTextCursor || (blinkingCursor.ElapsedMilliseconds > TEXT_CURSOR_BLINK_FREQUENCY && - (FocusedWidget is IEditableTextWidget || textCursor != null)); #region GraphicTree handling /// <summary>Add widget to the Graphic tree of this interface and register it for layouting</summary> @@ -1814,6 +1793,10 @@ namespace Crow // } return true; + } catch (Exception e) { + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + return true; } finally { Monitor.Exit (UpdateMutex); DbgLogger.EndEvent (DbgEvtType.MouseUp); @@ -1853,8 +1836,12 @@ namespace Crow } public virtual bool OnKeyDown (KeyEventArgs e) { + if (e.Key == Key.F5) { + registerRefreshClientRectangle(); + e.Handled = true; + } #if DEBUG_STATS - if (Shift && key == Key.F1) { + if (e.Modifiers == Modifier.Shift && e.Key == Key.F1) { LoadIMLFragment (@" <Window Caption='Debug Statistick' Width='50%' Height='50%' Background='DarkGrey'> <VerticalStack> diff --git a/Crow/src/ItemTemplate.cs b/Crow/src/ItemTemplate.cs index 9c67d57e..cf5bcab3 100644 --- a/Crow/src/ItemTemplate.cs +++ b/Crow/src/ItemTemplate.cs @@ -210,7 +210,7 @@ namespace Crow il.Emit (OpCodes.Br, gotoEnd); il.MarkLabel(gotoItemsContainerNotFound); - il.EmitWriteLine("ItemsContainer not found in ItemTemplate for " + host.ToString()); + il.EmitWriteLine($"[{dm.Name}] ItemsContainer not found in ItemTemplate for {host.ToString()}"); il.MarkLabel(gotoEnd); diff --git a/Crow/src/ObservableList.cs b/Crow/src/ObservableList.cs index 3cfe101a..a62e7e3a 100644 --- a/Crow/src/ObservableList.cs +++ b/Crow/src/ObservableList.cs @@ -139,14 +139,20 @@ namespace Crow public static ObservableList<T> Parse (string str) { ObservableList<T> tmp = new ObservableList<T>(); - Type t = typeof(T); - MethodInfo miParse = t.GetMethod ("Parse", BindingFlags.Static | BindingFlags.Public, - Type.DefaultBinder, new Type [] {typeof (string)}, null); - if (miParse == null) - throw new Exception ("no Parse method found for: " + t.FullName); if (!string.IsNullOrEmpty (str)) { - foreach (string s in str.Split(';')) - tmp.Add((T)miParse.Invoke (null, new object[] {s})); + Type t = typeof(T); + if (t.IsEnum) { + foreach (string s in str.Split(';')) + tmp.Add((T)Enum.Parse(t, s)); + } else { + MethodInfo miParse = t.GetMethod ("Parse", + BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder, new Type [] {typeof (string)}, null); + if (miParse == null) + throw new Exception ("no Parse method found for: " + t.FullName); + + foreach (string s in str.Split(';')) + tmp.Add((T)miParse.Invoke (null, new object[] {s})); + } } return tmp; } diff --git a/Crow/src/Text/CharLocation.cs b/Crow/src/Text/CharLocation.cs index 0d07b302..345f8fa3 100644 --- a/Crow/src/Text/CharLocation.cs +++ b/Crow/src/Text/CharLocation.cs @@ -11,14 +11,20 @@ namespace Crow.Text { public readonly int Line; /// <summary> - /// Character position in current line. If equals '-1', the visualX must contains the on screen position. - /// + /// Character position in current line. + /// If Column value is '-1', the visualX must contains the on screen position, and column will be computed from it. /// </summary> public int Column; + /// <summary> + /// The column as presented to the user, counting spaces in tabulations. + /// Its value is set during computations. + /// </summary> + public int TabulatedColumn; public double VisualCharXPosition; public CharLocation (int line, int column, double visualX = -1) { Line = line; Column = column; + TabulatedColumn = -1; VisualCharXPosition = visualX; } public bool HasVisualX => Column >= 0 && VisualCharXPosition >= 0; diff --git a/Crow/src/Text/Extensions.cs b/Crow/src/Text/Extensions.cs index b0b87180..77360ddd 100644 --- a/Crow/src/Text/Extensions.cs +++ b/Crow/src/Text/Extensions.cs @@ -7,27 +7,26 @@ namespace Crow.Text { public static class Extensions { - public static ReadOnlySpan<char> GetLine (this string str, TextLine ls) { + public static ReadOnlySpan<char> GetLine (this ReadOnlySpan<char> str, TextLine ls) { if (ls.Start >= str.Length) return "".AsSpan (); - return str.AsSpan ().Slice (ls.Start, ls.Length); + return str.Slice (ls.Start, ls.Length); } - public static ReadOnlySpan<char> GetLine (this string str, TextLine ls, int offset) { + public static ReadOnlySpan<char> GetLine (this ReadOnlySpan<char> str, TextLine ls, int offset) { int start = ls.Start + offset; if (start >= str.Length) return "".AsSpan (); - return str.AsSpan ().Slice (start, ls.Length); - + return str.Slice (start, ls.Length); } public static ReadOnlySpan<char> GetLineIncludingLineBreak (this string str, TextLine ls) { if (ls.Start >= str.Length) return "".AsSpan (); return str.AsSpan ().Slice (ls.Start, ls.LengthIncludingLineBreak); } - public static ReadOnlySpan<char> GetLineBreak (this string str, TextLine ls) { + public static ReadOnlySpan<char> GetLineBreak (this ReadOnlySpan<char> str, TextLine ls) { if (ls.LineBreakLength == 0) return "".AsSpan (); - return str.AsSpan ().Slice (ls.End, ls.LineBreakLength); + return str.Slice (ls.End, ls.LineBreakLength); } public static ReadOnlySpan<char> GetLineIncludingLineBreak (this string str, TextLine ls, int offset) { int start = ls.Start + offset; diff --git a/Crow/src/Text/SpanCharReader.cs b/Crow/src/Text/SpanCharReader.cs index ae55d64f..60fb432b 100644 --- a/Crow/src/Text/SpanCharReader.cs +++ b/Crow/src/Text/SpanCharReader.cs @@ -12,17 +12,26 @@ namespace Crow.Text int curPos; ReadOnlySpan<char> buffer; + [Obsolete] public SpanCharReader (string text) { buffer = text.AsSpan (); curPos = 0; } + public SpanCharReader (ReadOnlySpan<char> text) { + buffer = text; + curPos = 0; + } public int CurrentPosition => curPos; + /// <summary> + /// Current reader position is further the end of the buffer. + /// </summary> + public bool EndOfSpan => curPos >= buffer.Length; public void Seek (int position) => curPos = position; - public Char Peak => buffer[curPos]; - public Char Read () => buffer[curPos++]; + public char Peek => buffer[curPos]; + public char Read () => buffer[curPos++]; public bool TryRead (out char c) { if (EndOfSpan) { c = default; @@ -39,6 +48,24 @@ namespace Crow.Text curPos += increment; return curPos < buffer.Length; } + /// <summary> + /// Retrieve a span of that buffer from provided starting position to the current reader position. + /// </summary> + /// <param name="fromPosition"></param> + /// <returns></returns> + public ReadOnlySpan<char> Get (int fromPosition) => buffer.Slice (fromPosition, curPos - fromPosition); + public bool TryPeek (char c) => !EndOfSpan && Peek == c; + /// <summary> + /// Try peak one char, return false if end of span, true otherwise. + /// </summary> + /// <param name="c"></param> + /// <returns></returns> + public bool TryPeek (ref char c) { + if (EndOfSpan) + return false; + c = buffer[curPos]; + return true; + } public bool TryReadUntil (ReadOnlySpan<char> str, StringComparison comparison = StringComparison.Ordinal) { int startPos = curPos; @@ -79,33 +106,11 @@ namespace Crow.Text curPos += expectedString.Length; return res; } - public bool TryPeak (ReadOnlySpan<char> expectedString, StringComparison comparison = StringComparison.Ordinal) => + public bool TryPeek (ReadOnlySpan<char> expectedString, StringComparison comparison = StringComparison.Ordinal) => (buffer.Length < curPos + expectedString.Length)? false : buffer.Slice(curPos, expectedString.Length).Equals (expectedString, comparison); /// <summary> - /// Retrieve a span of that buffer from provided starting position to the current reader position. - /// </summary> - /// <param name="fromPosition"></param> - /// <returns></returns> - public ReadOnlySpan<char> Get (int fromPosition) => buffer.Slice (fromPosition, curPos - fromPosition); - /// <summary> - /// Current reader position is further the end of the buffer. - /// </summary> - public bool EndOfSpan => curPos >= buffer.Length; - public bool TryPeak (char c) => !EndOfSpan && Peak == c; - /// <summary> - /// Try peak one char, return false if end of span, true otherwise. - /// </summary> - /// <param name="c"></param> - /// <returns></returns> - public bool TryPeak (ref char c) { - if (EndOfSpan) - return false; - c = buffer[curPos]; - return true; - } - /// <summary> /// test if next char is one of the provided one as parameter /// </summary> /// <param name="chars"></param> @@ -121,7 +126,7 @@ namespace Crow.Text /// </summary> public void AdvanceUntilEol () { while(!EndOfSpan) { - switch (Peak) { + switch (Peek) { case '\x85': case '\x2028': case '\xA': @@ -140,8 +145,8 @@ namespace Crow.Text /// </summary> /// <returns></returns> public bool Eol () { - return Peak == '\x85' || Peak == '\x2028' || Peak == '\xA' || curPos + 1 == buffer.Length || - (Peak == '\xD' && (buffer [curPos + 1] == '\xA' || buffer [curPos + 1] == '\x85')); + return Peek == '\x85' || Peek == '\x2028' || Peek == '\xA' || curPos + 1 == buffer.Length || + (Peek == '\xD' && (buffer [curPos + 1] == '\xA' || buffer [curPos + 1] == '\x85')); } /// <summary> diff --git a/Crow/src/Text/TextChange.cs b/Crow/src/Text/TextChange.cs index 6aae62b1..ae1362a4 100644 --- a/Crow/src/Text/TextChange.cs +++ b/Crow/src/Text/TextChange.cs @@ -14,7 +14,7 @@ namespace Crow.Text public readonly string ChangedText; public int End => Start + Length; - public int End2 => Start + (string.IsNullOrEmpty (ChangedText) ? 0 : CharDiff); + public int End2 => End + CharDiff; public int CharDiff => string.IsNullOrEmpty (ChangedText) ? - Length : ChangedText.Length - Length; public TextChange (int position, int length, string changedText) { @@ -22,8 +22,14 @@ namespace Crow.Text Length = length; ChangedText = changedText; } - public TextChange Inverse (string src) + public TextChange (int position, int length, ReadOnlySpan<char> changedText) { + Start = position; + Length = length; + ChangedText = changedText.ToString(); + } + public TextChange Inverse (ReadOnlySpan<char> src) => new TextChange (Start, string.IsNullOrEmpty (ChangedText) ? 0 : ChangedText.Length, - Length == 0 ? "" : src.AsSpan (Start, Length).ToString ()); + Length == 0 ? "" : src.Slice (Start, Length).ToString ()); + public override string ToString() => $"{Start},{ChangedText}"; } } diff --git a/Crow/src/Text/TextLineCollection.cs b/Crow/src/Text/TextLineCollection.cs index ba40e084..5031496b 100644 --- a/Crow/src/Text/TextLineCollection.cs +++ b/Crow/src/Text/TextLineCollection.cs @@ -118,9 +118,7 @@ namespace Crow.Text int result = lines.AsSpan (0, length).BinarySearch (tl); if (result < 0) { result = ~result; - return result == 0 ? - new CharLocation (0, absolutePosition) : - new CharLocation (result - 1, absolutePosition - lines[result - 1].Start); + return new CharLocation (result - 1, absolutePosition - lines[result - 1].Start); } return new CharLocation (result, absolutePosition - lines[result].Start); } diff --git a/Crow/src/Widgets/DockStack.cs b/Crow/src/Widgets/DockStack.cs index 6d1a835d..60644c15 100644 --- a/Crow/src/Widgets/DockStack.cs +++ b/Crow/src/Widgets/DockStack.cs @@ -200,7 +200,6 @@ namespace Crow int vTreshold = (int)(r.Height * dockThresh); int hTreshold = (int)(r.Width * dockThresh); - System.Diagnostics.Debug.WriteLine ("Docking {0} as {2} in {1}", dw.Name, activeStack.Name, dw.DockingPosition); switch (dw.DockingPosition) { case Alignment.Top: dw.Height = vTreshold; @@ -237,8 +236,6 @@ namespace Crow public void Undock (DockWindow dw){ int idx = Children.IndexOf(dw); - System.Diagnostics.Debug.WriteLine ("undocking child index: {0} ; name={1}; pos:{2} ; childcount:{3}",idx, dw.Name, dw.DockingPosition, Children.Count); - RemoveChild(dw); if (Children.Count == 0)//TODO:empty Stack should be removed if not root stack I guess diff --git a/Crow/src/Widgets/DockWindow.cs b/Crow/src/Widgets/DockWindow.cs index 0fc8a825..43fd8a9a 100644 --- a/Crow/src/Widgets/DockWindow.cs +++ b/Crow/src/Widgets/DockWindow.cs @@ -131,8 +131,6 @@ namespace Crow dockParentParent = false; Rectangle r = default; - Console.WriteLine ($"onDrag target={IFace.DragAndDropOperation.DropTarget}"); - if (IFace.DragAndDropOperation.DropTarget is DockStack ds) { ds.onDragMouseMove (this, e); r = ds.ScreenCoordinates (ds.LastPaintedSlot); @@ -149,7 +147,6 @@ namespace Crow dwCb.Inflate (-4,-4); if (tryGetTargetDockStack (dw, out DockStack targetStack)) { - Console.WriteLine ($"exterior: {!dwCb.ContainsOrIsEqual (m)} targetStack.Parent: {targetStack.Parent.GetType()}"); if (dwCb.ContainsOrIsEqual (m)) { r = dw.ScreenCoordinates (dw.LastPaintedSlot); } else if (targetStack.Parent is DockStack) { @@ -197,9 +194,11 @@ namespace Crow r.Width /= 4; break; case Alignment.Center: - r.Inflate (r.Width / -3, r.Height / -3); + r.Inflate (r.Width / -4, r.Height / -4); + Console.WriteLine(r); break; } + r.Inflate(-2,-2); ISurface dragImg = IFace.Backend.CreateSurface (r.Width, r.Height); using (IContext gr = IFace.Backend.CreateContext (dragImg)) { gr.LineWidth = 1; @@ -293,9 +292,6 @@ namespace Crow } } bool checkUndock (Point mousePos) { - //if (DockingPosition == Alignment.Center) - // return false; - System.Diagnostics.Debug.WriteLine ($"{mousePos.X},{mousePos.Y}"); if (Math.Abs (mousePos.X - undockingMousePosOrig.X) < undockThreshold || Math.Abs (mousePos.X - undockingMousePosOrig.X) < undockThreshold) return false; diff --git a/Crow/src/Widgets/GroupBase.cs b/Crow/src/Widgets/GroupBase.cs index e99b176e..3a3e72c9 100644 --- a/Crow/src/Widgets/GroupBase.cs +++ b/Crow/src/Widgets/GroupBase.cs @@ -238,6 +238,9 @@ namespace Crow { for (int i = 0; i < Children.Count; i++) Children[i].Paint (gr); + } catch (Exception e) { + Console.WriteLine($"Erreur group {this} paint: {e.Message}"); + Console.WriteLine(e.StackTrace); } finally { childrenRWLock.ExitReadLock (); } diff --git a/Crow/src/Widgets/Image.cs b/Crow/src/Widgets/Image.cs index 2c102c22..b1a3a94f 100644 --- a/Crow/src/Widgets/Image.cs +++ b/Crow/src/Widgets/Image.cs @@ -8,6 +8,13 @@ using System.Xml.Serialization; using System.ComponentModel; using System.Diagnostics; using Drawing2D; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.IO; +using System.Linq; +using System.Collections; +using System.Collections.Generic; namespace Crow { @@ -69,16 +76,14 @@ namespace Crow try { if (string.IsNullOrEmpty(value)) Picture = null; - else { - //lock(IFace.LayoutMutex){ - LoadImage (value); - //} - } + else + LoadImage (value); } catch (Exception ex) { Debug.WriteLine (ex.Message); _pic = null; } NotifyValueChangedAuto (Path); + RegisterForGraphicUpdate(); } } /// <summary> @@ -140,15 +145,64 @@ namespace Crow #endregion #region Image Loading + static HttpClient http = new HttpClient(); + static int HTTP_DOWNLOAD_TIMEOUT_MS = 5000; + void downloadThread(Uri uri) { + Picture pic = null; + var getcontenttype = http.GetAsync(uri); + var task = http.GetStreamAsync(uri); + if (getcontenttype.Wait(HTTP_DOWNLOAD_TIMEOUT_MS) && getcontenttype.IsCompletedSuccessfully) { + if (!getcontenttype.Result.Content.Headers.TryGetValues("content-Type", out IEnumerable<string> contents)) + return; + string[] type = contents.FirstOrDefault().Split('/'); + if (!string.Equals(type[0], "image", StringComparison.Ordinal)) + return; + if (string.Equals(type[1], "svg", StringComparison.Ordinal)) + pic = new SvgPicture(uri.AbsoluteUri); + else if (string.Equals(type[1], "png", StringComparison.Ordinal)) + pic = new BmpPicture(uri.AbsoluteUri); + else { + Debug.WriteLine($"Unsupported image format for download: {type[1]}"); + return; + } + + if (task.Wait(HTTP_DOWNLOAD_TIMEOUT_MS) && task.IsCompletedSuccessfully) { + MemoryStream dataCopy = new MemoryStream(); + task.Result.CopyTo(dataCopy); + dataCopy.Position = 0; + pic.LoadFromStream(IFace, dataCopy); + pic.Scaled = scaled; + pic.KeepProportions = keepProps; + lock(IFace.UpdateMutex) + Picture = pic; + } + } + + } + public void LoadImage (string path) { Picture pic; + if (path.StartsWith("url:", StringComparison.OrdinalIgnoreCase)) { + /*if (IFace.sharedPictures.ContainsKey (Path)) { + sharedPicture sp = IFace.sharedPictures [Path]; + if (sp.Data is ISvgHandle svgHandle) { + pic = new SvgPicture() + } + }*/ + Uri uri = new Uri(path.Substring (4)); + if (string.IsNullOrEmpty(uri.AbsolutePath)) + return; + Thread download = new Thread(()=>downloadThread(uri)); + download.Start(); + return; + } + if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture)) pic = new SvgPicture (path); else pic = new BmpPicture (path); - pic.Scaled = scaled; pic.KeepProportions = keepProps; diff --git a/Crow/src/Widgets/Label.cs b/Crow/src/Widgets/Label.cs index f5b4fb1c..a35151ea 100644 --- a/Crow/src/Widgets/Label.cs +++ b/Crow/src/Widgets/Label.cs @@ -289,10 +289,10 @@ namespace Crow LineBreak = Environment.NewLine; return; } - LineBreak = _text.GetLineBreak (lines[0]).ToString (); + LineBreak = _text.AsSpan().GetLineBreak (lines[0]).ToString (); for (int i = 1; i < lines.Count; i++) { - ReadOnlySpan<char> lb = _text.GetLineBreak (lines[i]); + ReadOnlySpan<char> lb = _text.AsSpan().GetLineBreak (lines[i]); if (!lb.SequenceEqual (LineBreak)) { mixedLineBreak = true; break; @@ -377,7 +377,7 @@ namespace Crow if (lines[i].Length == 0) lines.UpdateLineLengthInPixel (i, 0);// (int)Math.Ceiling (fe.MaxXAdvance); else { - gr.TextExtents (_text.GetLine (lines[i]), Interface.TAB_SIZE, out tmp); + gr.TextExtents (_text.AsSpan().GetLine (lines[i]), Interface.TAB_SIZE, out tmp); lines.UpdateLineLengthInPixel (i, (int)Math.Ceiling (tmp.XAdvance)); } } @@ -420,8 +420,7 @@ namespace Crow selStart = SelectionStart.Value; selEnd = CurrentLoc.Value; } - } else - IFace.forceTextCursor = true; + } } if (!string.IsNullOrEmpty (_text)) { @@ -439,7 +438,7 @@ namespace Crow if (bytes.Length < size) bytes = size > 512 ? new byte[size] : stackalloc byte[size]; - encodedBytes = _text.GetLine (lines[i]).ToUtf8 (bytes); + encodedBytes = _text.AsSpan().GetLine (lines[i]).ToUtf8 (bytes); bytes[encodedBytes++] = 0; if (lines[i].LengthInPixel < 0) { @@ -555,8 +554,8 @@ namespace Crow return false; } - Rectangle c = ScreenCoordinates (textCursor.Value + Slot.Position + ClientRectangle.Position); - ctx.ResetClip(); + Rectangle c = ContextCoordinates(textCursor.Value + Slot.Position + ClientRectangle.Position); + Foreground.SetAsSource (IFace, ctx, c); ctx.LineWidth = 1.0; ctx.MoveTo (0.5 + c.X, c.Y); @@ -574,7 +573,7 @@ namespace Crow if (loc.HasVisualX) return; TextLine ls = lines[loc.Line]; - ReadOnlySpan<char> curLine = _text.GetLine (ls); + ReadOnlySpan<char> curLine = _text.AsSpan().GetLine (ls); double cPos = getX (clientWidth, ls); if (loc.Column >= 0) { @@ -733,7 +732,7 @@ namespace Crow else if (!SelectionStart.HasValue) SelectionStart = CurrentLoc; CurrentLoc = hoverLoc; - IFace.forceTextCursor = true; + IFace.forceTextCursor(); RegisterForRedraw (); e.Handled = true; } @@ -820,7 +819,7 @@ namespace Crow base.onKeyDown (sender, e); return; } - IFace.forceTextCursor = true; + IFace.forceTextCursor(); e.Handled = true; } #endregion diff --git a/Crow/src/Widgets/TextBox.cs b/Crow/src/Widgets/TextBox.cs index ff9bec25..5d58c606 100644 --- a/Crow/src/Widgets/TextBox.cs +++ b/Crow/src/Widgets/TextBox.cs @@ -220,8 +220,15 @@ namespace Crow return cursor; } - - void updateMaxScrolls (LayoutingType layout) { + public override bool Paint(IContext ctx) + { + bool painted = base.Paint(ctx); + if (HasFocus && painted && IFace.drawTextCursor) { + DrawCursor(ctx, out Rectangle r); + } + return painted; + } + void updateMaxScrolls (LayoutingType layout) { Rectangle cb = ClientRectangle; if (layout == LayoutingType.Width) { MaxScrollX = cachedTextSize.Width - cb.Width; @@ -339,7 +346,7 @@ namespace Crow } #endregion - protected void update (TextChange change) { + protected void update (TextChange change, int charLocOffset = 0) { lock (linesMutex) { ReadOnlySpan<char> src = Text.AsSpan (); Span<char> tmp = stackalloc char[src.Length + (change.ChangedText.Length - change.Length)]; @@ -353,9 +360,9 @@ namespace Crow //lines.Update (_text); SelectionStart = null; - CurrentLoc = lines.GetLocation (change.Start + change.ChangedText.Length); + CurrentLoc = lines.GetLocation (change.Start + change.ChangedText.Length + charLocOffset); textMeasureIsUpToDate = false; - IFace.forceTextCursor = true; + IFace.forceTextCursor(); } NotifyValueChanged ("Text", Text); diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index e3703119..bebb57a3 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -409,7 +409,8 @@ namespace Crow [XmlIgnore]public virtual Rectangle ClientRectangle { get { Rectangle cb = Slot.Size; - cb.Inflate ( - margin); + cb.Inflate (-margin); + //return cb.IsValid ? cb : Slot.Size; return cb; } } @@ -1986,10 +1987,10 @@ namespace Crow } /// <summary> Chained painting routine on the parent context of the actual cached version /// of the widget </summary> - public virtual void Paint (IContext ctx) + public virtual bool Paint (IContext ctx) { if (!IsVisible) - return; + return false; DbgLogger.StartEvent (DbgEvtType.GOPaint, this); @@ -2006,7 +2007,7 @@ namespace Crow #endif DbgLogger.AddEvent (DbgEvtType.Warning); DbgLogger.EndEvent (DbgEvtType.GOPaint); - return; + return false; } //lock (this) { if (cacheEnabled) { @@ -2044,6 +2045,7 @@ namespace Crow Painted.Raise (this, null); DbgLogger.EndEvent (DbgEvtType.GOPaint); + return true; } void paintDisabled(IContext gr, Rectangle rb){ //gr.Operator = Operator.Xor; diff --git a/Crow/src/Widgets/Window.cs b/Crow/src/Widgets/Window.cs index cc7763c9..389b1668 100644 --- a/Crow/src/Widgets/Window.cs +++ b/Crow/src/Widgets/Window.cs @@ -9,6 +9,9 @@ using Drawing2D; namespace Crow { + /// <summary> + /// + /// </summary> public class Window : TemplatedContainer { public enum Direction diff --git a/Directory.Build.props b/Directory.Build.props index eb7ad1da..e1bd3e46 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,7 @@ <Authors>Jean-Philippe Bruyère</Authors> <LangVersion>7.3</LangVersion> - <CrowVersion>1.3.1</CrowVersion> + <CrowVersion>1.3.2</CrowVersion> <CrowPackageVersion>$(CrowVersion)-beta</CrowPackageVersion> <!-- If you dont have a native libstb on your system, enable the managed version of stb here @@ -15,7 +15,7 @@ <!-- Compile with logging enabled, this will slow down apps, use this only for debugging purpose--> - <CrowDebugLogEnabled>false</CrowDebugLogEnabled> + <CrowDebugLogEnabled>true</CrowDebugLogEnabled> <!-- Collect several statistics on widgets--> <CrowDebugStatsEnabled>false</CrowDebugStatsEnabled> diff --git a/Drawing2D/Drawing2D.csproj b/Drawing2D/Drawing2D.csproj index b126ddff..72123f26 100644 --- a/Drawing2D/Drawing2D.csproj +++ b/Drawing2D/Drawing2D.csproj @@ -4,7 +4,7 @@ <TargetFramework>netstandard2.1</TargetFramework> <EnableDefaultCompileItems>false</EnableDefaultCompileItems> - <AssemblyVersion>1.2.0</AssemblyVersion> + <AssemblyVersion>1.2.1</AssemblyVersion> <PackageVersion>$(AssemblyVersion)-beta</PackageVersion> <Title>Drawing 2D Library</Title> diff --git a/Drawing2D/src/DbgEvtType.cs b/Drawing2D/src/DbgEvtType.cs index ff214ec8..e54c5603 100644 --- a/Drawing2D/src/DbgEvtType.cs +++ b/Drawing2D/src/DbgEvtType.cs @@ -27,7 +27,8 @@ namespace Crow Dispose = 0x00100000, Mouse = 0x00200000, DragNDrop = 0x00400000, - + Ressources = 0x00800000,//image loading... + Update = IFace | 0x10000000, ProcessLayouting = IFace | Update | Lock | Layouting, ClippingRegistration = IFace | Update | Lock | Clipping, @@ -107,6 +108,7 @@ namespace Crow EndDrag = Widget | DragNDrop | 0x05, Drop = Widget | DragNDrop | 0x06, + LayoutingLoopError = Layouting | Error | 0x01, All = 0x7FFFFF00 } }
\ No newline at end of file diff --git a/Drawing2D/src/Encoding.cs b/Drawing2D/src/Encoding.cs index 8999623d..58cdf601 100644 --- a/Drawing2D/src/Encoding.cs +++ b/Drawing2D/src/Encoding.cs @@ -7,10 +7,10 @@ namespace Drawing2D { public static class Extensions { - public static int ToUtf8 (this ReadOnlySpan<char> source, Span<byte> buff, int tabWidth = 4) { + public static int ToUtf8 (this ReadOnlySpan<char> source, Span<byte> buff, ref int encodedChar, int tabWidth = 4) { int c = 0; int encodedBytes = 0; - int encodedChar = 0; + while (c < source.Length) { if (source[c] < 0xD800) { if (source[c] == '\t') { @@ -44,6 +44,10 @@ namespace Drawing2D } buff[encodedBytes] = 0; return encodedBytes; + } + public static int ToUtf8 (this ReadOnlySpan<char> source, Span<byte> buff, int tabWidth = 4) { + int encodedChar = 0; + return ToUtf8(source,buff,ref encodedChar, tabWidth); } diff --git a/Drawing2D/src/Rectangle.cs b/Drawing2D/src/Rectangle.cs index ac0d83c7..d120de69 100644 --- a/Drawing2D/src/Rectangle.cs +++ b/Drawing2D/src/Rectangle.cs @@ -61,7 +61,7 @@ namespace Drawing2D { public Point BottomRight => new Point (Right, Bottom); public Point Center => new Point (Left + Width / 2, Top + Height / 2); public Point CenterD => new PointD (Left + Width / 2.0, Top + Height / 2.0); - + public bool IsValid => Width > 0 && Height > 0; #endregion #region FUNCTIONS diff --git a/Drawing2D/src/RectangleD.cs b/Drawing2D/src/RectangleD.cs index 2d3f3931..c5d12313 100644 --- a/Drawing2D/src/RectangleD.cs +++ b/Drawing2D/src/RectangleD.cs @@ -60,7 +60,7 @@ namespace Drawing2D { public PointD BottomRight => new PointD (Right, Bottom); public PointD Center => new PointD (Left + Width / 2, Top + Height / 2); public PointD CenterD => new PointD (Left + Width / 2.0, Top + Height / 2.0); - + public bool IsValid => Width > 0 && Height > 0; #endregion #region FUNCTIONS diff --git a/Drawing2D/src/Size.cs b/Drawing2D/src/Size.cs index acd5c06c..dd3a6c1b 100644 --- a/Drawing2D/src/Size.cs +++ b/Drawing2D/src/Size.cs @@ -50,7 +50,7 @@ namespace Drawing2D public static Size operator * (Size s, double i) => new Size ((int)(s.Width * i), (int)(s.Height * i)); #endregion - + public bool IsValid => Width > 0 && Height > 0; public bool Equals (Size other) => Width == other.Width && Height == other.Height; public bool Equals (int other) => Width == other && Height == other; diff --git a/Drawing2D/src/SizeD.cs b/Drawing2D/src/SizeD.cs index dd466491..93f7698c 100644 --- a/Drawing2D/src/SizeD.cs +++ b/Drawing2D/src/SizeD.cs @@ -48,6 +48,7 @@ namespace Drawing2D public static SizeD operator / (SizeD s, double i) => new SizeD (s.Width / i, s.Height / i); #endregion + public bool IsValid => Width > 0 && Height > 0; public override int GetHashCode () => HashCode.Combine (Width, Height); public override bool Equals (object obj) => obj is SizeD s ? Equals (s) : false; public bool Equals(SizeD other) => Width == other.Width && Height == other.Height; diff --git a/Samples/AnimTest/AnimTest.csproj b/Samples/AnimTest/AnimTest.csproj index 178d4537..5ab677ea 100644 --- a/Samples/AnimTest/AnimTest.csproj +++ b/Samples/AnimTest/AnimTest.csproj @@ -1,11 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk"> - <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> - <OutputType>Exe</OutputType> - </PropertyGroup> - <ItemGroup> - <PackageReference Include="Crow" /> - </ItemGroup> </Project>
\ No newline at end of file diff --git a/Samples/HelloWorld/HelloWorld.csproj b/Samples/HelloWorld/HelloWorld.csproj index 6c6cdaf7..4c64f057 100644 --- a/Samples/HelloWorld/HelloWorld.csproj +++ b/Samples/HelloWorld/HelloWorld.csproj @@ -1,6 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> - <PackageReference Include="Crow" /> - </ItemGroup> + <EmbeddedResource Include="ui\*.*"> + <LogicalName>ui.%(Filename)%(Extension)</LogicalName> + </EmbeddedResource> + </ItemGroup> </Project>
\ No newline at end of file diff --git a/Samples/HelloWorld/main.cs b/Samples/HelloWorld/main.cs index 54429171..50255ac9 100644 --- a/Samples/HelloWorld/main.cs +++ b/Samples/HelloWorld/main.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Crow; using Glfw; using Samples; @@ -11,8 +12,11 @@ namespace HelloWorld //Interface.PreferedBackendType = Drawing2D.BackendType.Egl; using (Program app = new Program ()) { //app.Initialized += (sender, e) => app.LoadIMLFragment (@"<Label Text='Hello World' Background='Red' Top='50' Margin='0'/>"); - app.Initialized += (sender, e) => app.LoadIMLFragment (@"<Container Width='Stretched' ><Window Caption='hello world' Background='Jet'/></Container>"); + //app.Initialized += (sender, e) => app.LoadIMLFragment (@"<Container Width='Stretched' ><Window Caption='hello world' Background='Jet'/></Container>"); + app.Initialized += (sender, e) => app.Load("#ui.helloworld.crow"); app.Run (); + + DbgLogger.Save(app); } } } diff --git a/Samples/HelloWorld/ui/helloworld.crow b/Samples/HelloWorld/ui/helloworld.crow index 874667c2..c3187a8a 100644 --- a/Samples/HelloWorld/ui/helloworld.crow +++ b/Samples/HelloWorld/ui/helloworld.crow @@ -1,9 +1,11 @@ <?xml version="1.0"?> - - <!--<Widget Background="hgradient|0:Black|0.5:Blue|1:Red" Margin="100" />--> - <VerticalStack> - <Image Path="#Crow.Icons.checkbox.svg" SvgSub="True" Height="200"/> - <CheckBox/> - - </VerticalStack> - <!--<ColorPicker/>--> +<VerticalStack> +<TextBox Margin="10"/> +</VerticalStack> +<!--<Group CacheEnabled="false" Name="dockRoot" Margin="20" Focusable="true" Width="Stretched" Height="Stretched"> + <DockStack ClipToClientRect="false" CacheEnabled="false" Name="mainDock" Focusable="false" Width="50%" Background="0.1,0.1,0.1,0.8"/> + <DockWindow Name="win1" Style="SimpleDockWin" Top="10" Left="10" Background="Red" Width="200" Height="200"/> + <DockWindow Name="win2" Style="SimpleDockWin" Top="30" Left="30" Background="Green" Width="200" Height="200"/> + <DockWindow Name="win3" Style="SimpleDockWin" Top="50" Left="50" Background="Pink" Width="200" Height="200"/> + <DockWindow Name="win4" Style="SimpleDockWin" Top="70" Left="70" Background="RoyalBlue" Width="200" Height="200"/> +</Group>--> diff --git a/Samples/PerfTests/Program.cs b/Samples/PerfTests/Program.cs index ece49f6b..28c856a2 100644 --- a/Samples/PerfTests/Program.cs +++ b/Samples/PerfTests/Program.cs @@ -14,6 +14,7 @@ namespace PerfTests { class TestInterface : Interface { + public bool shouldClose = false; readonly int count = 10, updateCycles = 0; readonly bool screenOutput = false; readonly string inDirectory = null;//directory to test @@ -61,6 +62,7 @@ namespace PerfTests Console.WriteLine ("-u,--update:\n\tmeasure 'n' update cycle with elapsed ticks string notified. (default = 0)"); Console.WriteLine ("-s,--screen:\n\tenable output to screen."); Console.WriteLine ("-h,--help:\n\tthis help message."); + shouldClose = true; } public TestInterface (string[] args, int width = 800, int height = 600) @@ -113,15 +115,17 @@ namespace PerfTests case "-h": case "--help": default: - throw new Exception ("none"); + printHelp (); + return; } } if (EndStage < StartStage) throw new Exception ($"Ending stage (){EndStage} is before Starting stage ({StartStage})"); } catch (Exception e) { + Console.WriteLine($"Invalid command line parameters: {e.Message}"); printHelp (); - throw e; + return; } if (string.IsNullOrEmpty (outDir)) { @@ -158,7 +162,7 @@ namespace PerfTests } protected override void initBackend() { - if (!tryFindBackendType (out Type backendType)) + if (!tryFindBackend (out Type backendType)) throw new Exception ("No backend found."); if (screenOutput) backend = (Drawing2D.CrowBackend)Activator.CreateInstance (backendType, new object[] {clientRectangle.Width, clientRectangle.Height, hWin}); @@ -505,17 +509,17 @@ namespace PerfTests try { using (TestInterface iface = new TestInterface (args)) { - if (string.IsNullOrEmpty(iface.inDirectory)) - iface.PerformUnitTests (); - else - iface.PerformTests (); + if (!iface.shouldClose) { + if (string.IsNullOrEmpty(iface.inDirectory)) + iface.PerformUnitTests (); + else + iface.PerformTests (); + } } } catch (Exception e) { - if (e.Message != "none") { - Console.ForegroundColor = ConsoleColor.DarkRed; - Console.WriteLine (e); - Console.ResetColor (); - } + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine (e); + Console.ResetColor (); } } } diff --git a/Samples/ShowCase/ShowCase.cs b/Samples/ShowCase/ShowCase.cs index 92a71e9f..125dc4b5 100644 --- a/Samples/ShowCase/ShowCase.cs +++ b/Samples/ShowCase/ShowCase.cs @@ -20,9 +20,10 @@ namespace ShowCase { class Showcase : SampleBaseForEditor { - DbgEvtType[] logEvts = { - DbgEvtType.IFace, - DbgEvtType.Widget + static DbgEvtType[] logEvts = { + /*DbgEvtType.IFace, + DbgEvtType.Widget,*/ + DbgEvtType.Ressources /*DbgEvtType.MouseEnter, DbgEvtType.MouseLeave, DbgEvtType.WidgetMouseDown, @@ -31,9 +32,12 @@ namespace ShowCase }; static void Main () { - //Interface.PreferedBackendType = Drawing2D.BackendType.Egl; + DbgLogger.ConsoleOutput = true; + DbgLogger.IncludedEvents.Add(DbgEvtType.Ressources); - initDebugLog (); + //Configuration.Global.Set ("RecordedEvents", new DbgEvtType[] { DbgEvtType.Ressources}); + + //Interface.PreferedBackendType = Drawing2D.BackendType.Egl; Environment.SetEnvironmentVariable ("FONTCONFIG_PATH", @"C:\Users\Jean-Philippe\source\vcpkg\installed\x64-windows\tools\fontconfig\fonts"); @@ -81,7 +85,6 @@ namespace ShowCase Terminate (); } - public Container crowContainer; Stopwatch reloadChrono = new Stopwatch (); @@ -157,9 +160,6 @@ namespace ShowCase NotifyValueChanged ("ShowError", false); } - - - protected override void OnInitialized () { base.OnInitialized (); diff --git a/Samples/ShowCase/ui/showcase.crow b/Samples/ShowCase/ui/showcase.crow index b1d6fb88..a7d7e97d 100644 --- a/Samples/ShowCase/ui/showcase.crow +++ b/Samples/ShowCase/ui/showcase.crow @@ -15,10 +15,15 @@ ContextCommands="{GetCommands}" Selected="{Background=${ControlHighlight}}" Unselected="{Background=Transparent}"> - <HorizontalStack> - <Image Margin="1" Width="14" Height="14" Path="#Crow.Icons.file.svg"/> - <Label Text="{Name}" Width="Stretched"/> - </HorizontalStack> + <Border CornerRadius="2" Margin="0" Height="Fit" + Foreground="Transparent" + MouseEnter="{Foreground=DimGrey}" + MouseLeave="{Foreground=Transparent}"> + <HorizontalStack> + <Image Margin="1" Width="14" Height="14" Path="#Crow.Icons.file.svg"/> + <Label Text="{Name}" Width="Stretched"/> + </HorizontalStack> + </Border> </ListItem> </ItemTemplate> <ItemTemplate DataType="System.IO.DirectoryInfo" Data="GetFileSystemInfosOrdered"> diff --git a/Samples/common/samples.style b/Samples/common/samples.style index 85012c13..4fbe0293 100644 --- a/Samples/common/samples.style +++ b/Samples/common/samples.style @@ -1,4 +1,10 @@ TestCst = "This is a constant test."; +InactiveTabBackground = "DarkGrey"; +SelectedTabBackground = "Onyx"; +InactiveTabForeground = "Grey"; +SelectedTabForeground = "White"; +SmallUIFont = "sans, 12"; +SmallFont = "consolas, 12"; FpsLabel { Width = "30"; diff --git a/Samples/common/src/Editor.cs b/Samples/common/src/Editor.cs index 13e0f382..d0befc6b 100644 --- a/Samples/common/src/Editor.cs +++ b/Samples/common/src/Editor.cs @@ -14,6 +14,7 @@ using System.Reflection; using System.Collections; using Drawing2D; +using System.Diagnostics; namespace Crow { @@ -49,21 +50,8 @@ namespace Crow bool suggestionsActive => overlay != null && overlay.IsVisible; Token currentToken; SyntaxNode currentNode; - string[] allWidgetNames = typeof (Widget).Assembly.GetExportedTypes ().Where(t=>typeof(Widget).IsAssignableFrom (t)) - .Select (s => s.Name).ToArray (); - IEnumerable<MemberInfo> getAllCrowTypeMembers (string crowTypeName) { - Type crowType = IFace.GetWidgetTypeFromName (crowTypeName); - return crowType.GetMembers (BindingFlags.Public | BindingFlags.Instance). - Where (m=>((m is PropertyInfo pi && pi.CanWrite) || (m is EventInfo)) && - m.GetCustomAttribute<XmlIgnoreAttribute>() == null); - } - MemberInfo getCrowTypeMember (string crowTypeName, string memberName) { - Type crowType = IFace.GetWidgetTypeFromName (crowTypeName); - return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault (); - } - public override void OnTextChanged(object sender, TextChangeEventArgs e) { base.OnTextChanged(sender, e); @@ -76,6 +64,67 @@ namespace Crow //Console.WriteLine ($"{pos}: {suggestionTok.AsString (_text)} {suggestionTok}"); } + + void showOverlay () { + lock (IFace.UpdateMutex) { + if (overlay == null) { + overlay = IFace.LoadIMLFragment<ListBox>(@" + <ListBox Style='suggestionsListBox' Data='{Suggestions}' UseLoadingThread='False' > + <ItemTemplate> + <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left' + Selected = '{Background=${ControlHighlight}}' + Unselected = '{Background=Transparent}'> + <Label Text='{}' HorizontalAlignment='Left' /> + </ListItem> + </ItemTemplate> + <ItemTemplate DataType='System.Reflection.MemberInfo'> + <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left' + Selected = '{Background=${ControlHighlight}}' + Unselected = '{Background=Transparent}'> + <HorizontalStack> + <Image Picture='{GetIcon}' Width='16' Height='16'/> + <Label Text='{Name}' HorizontalAlignment='Left' /> + </HorizontalStack> + </ListItem> + </ItemTemplate> + <ItemTemplate DataType='Colors'> + <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left' + Selected = '{Background=${ControlHighlight}}' + Unselected = '{Background=Transparent}'> + <HorizontalStack> + <Widget Background='{}' Width='20' Height='14'/> + <Label Text='{}' HorizontalAlignment='Left' /> + </HorizontalStack> + </ListItem> + </ItemTemplate> + </ListBox> + "); + overlay.DataSource = this; + overlay.Loaded += (sender, arg) => (sender as ListBox).SelectedIndex = 0; + } else + overlay.IsVisible = true; + overlay.RegisterForLayouting(LayoutingType.Sizing); + } + } + void hideOverlay () { + if (overlay == null) + return; + overlay.IsVisible = false; + } + + + string[] allWidgetNames = typeof (Widget).Assembly.GetExportedTypes ().Where(t=>typeof(Widget).IsAssignableFrom (t)) + .Select (s => s.Name).ToArray (); + IEnumerable<MemberInfo> getAllCrowTypeMembers (string crowTypeName) { + Type crowType = IFace.GetWidgetTypeFromName (crowTypeName); + return crowType?.GetMembers (BindingFlags.Public | BindingFlags.Instance). + Where (m=>((m is PropertyInfo pi && pi.CanWrite) || (m is EventInfo)) && + m.GetCustomAttribute<XmlIgnoreAttribute>() == null); + } + MemberInfo getCrowTypeMember (string crowTypeName, string memberName) { + Type crowType = IFace.GetWidgetTypeFromName (crowTypeName); + return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault (); + } void tryGetSuggestions () { if (!currentLoc.HasValue) return; @@ -88,7 +137,15 @@ namespace Crow Suggestions = new List<string> (allWidgetNames); } else if (currentToken.Type == TokenType.ElementName) { Suggestions = allWidgetNames.Where (s => s.StartsWith (currentToken.AsString (_text), StringComparison.OrdinalIgnoreCase)).ToList (); - } else if (currentNode is AttributeSyntax attribNode) { + } else if (currentToken.Type == TokenType.EndElementOpen && currentNode is ElementEndTagSyntax eltEndTag) { + ElementSyntax es = eltEndTag.Parent as ElementSyntax; + if (es?.StartTag != null) + Suggestions = new List<string> (new string[] {es.StartTag.NameToken.Value.AsString(_text)}); + } else if (currentToken.Type.HasFlag(TokenType.WhiteSpace) && typeof(ElementTagSyntax).IsAssignableFrom(currentNode?.GetType())) { + ElementTagSyntax ets = currentNode as ElementTagSyntax; + if (ets.NameToken.HasValue) + Suggestions = getAllCrowTypeMembers (ets.NameToken.Value.AsString (_text)).ToList (); + } else if (currentToken.Type != TokenType.AttributeValueClose && currentNode is AttributeSyntax attribNode) { if (currentNode.Parent is ElementTagSyntax eltTag) { if (eltTag.NameToken.HasValue) { if (currentToken.Type == TokenType.AttributeName) { @@ -153,71 +210,47 @@ namespace Crow hideOverlay (); } } - void showOverlay () { - lock (IFace.UpdateMutex) { - if (overlay == null) { - overlay = IFace.LoadIMLFragment<ListBox>(@" - <ListBox Style='suggestionsListBox' Data='{Suggestions}' UseLoadingThread='False' > - <ItemTemplate> - <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left' - Selected = '{Background=${ControlHighlight}}' - Unselected = '{Background=Transparent}'> - <Label Text='{}' HorizontalAlignment='Left' /> - </ListItem> - </ItemTemplate> - <ItemTemplate DataType='System.Reflection.MemberInfo'> - <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left' - Selected = '{Background=${ControlHighlight}}' - Unselected = '{Background=Transparent}'> - <HorizontalStack> - <Image Picture='{GetIcon}' Width='16' Height='16'/> - <Label Text='{Name}' HorizontalAlignment='Left' /> - </HorizontalStack> - </ListItem> - </ItemTemplate> - <ItemTemplate DataType='Colors'> - <ListItem Height='Fit' Margin='0' Focusable='false' HorizontalAlignment='Left' - Selected = '{Background=${ControlHighlight}}' - Unselected = '{Background=Transparent}'> - <HorizontalStack> - <Widget Background='{}' Width='20' Height='14'/> - <Label Text='{}' HorizontalAlignment='Left' /> - </HorizontalStack> - </ListItem> - </ItemTemplate> - </ListBox> - "); - overlay.DataSource = this; - overlay.Loaded += (sender, arg) => (sender as ListBox).SelectedIndex = 0; - } else - overlay.IsVisible = true; - overlay.RegisterForLayouting(LayoutingType.Sizing); - } - } - void hideOverlay () { - if (overlay == null) - return; - overlay.IsVisible = false; - } - void completeToken () { - string selectedSugg = overlay.SelectedItem is MemberInfo mi ? - mi.Name : overlay.SelectedItem?.ToString (); - if (selectedSugg == null) - return; - if (currentToken.Type == TokenType.ElementOpen || - currentToken.Type == TokenType.WhiteSpace || - currentToken.Type == TokenType.AttributeValueOpen) - update (new TextChange (currentToken.End, 0, selectedSugg)); - else if (currentToken.Type == TokenType.AttributeName && currentNode is AttributeSyntax attrib) { + void completeToken (string selectedSugg) { + if (currentToken.Type.HasFlag(TokenType.WhiteSpace)) { + if (typeof(ElementTagSyntax).IsAssignableFrom(currentNode?.GetType())) { + ElementTagSyntax ets = currentNode as ElementTagSyntax; + if (ets.NameToken.HasValue) + update (new TextChange (currentToken.End, 0, selectedSugg + "=\"\""),-1); + else + update (new TextChange (currentToken.End, 0, selectedSugg + " ")); + } else { + update (new TextChange (currentToken.End, 0, selectedSugg)); + } + } else if (currentToken.Type == TokenType.EndElementOpen) { + update (new TextChange (currentToken.End, 0, selectedSugg + ">")); + } else if (currentToken.Type == TokenType.ElementName) { + if (currentNode is ElementEndTagSyntax) + update (new TextChange (currentToken.Start, currentToken.Length, selectedSugg + ">")); + else + update (new TextChange (currentToken.Start, currentToken.Length, selectedSugg + ">"), -1); + } else if (currentNode is AttributeSyntax attrib) { + if (currentToken.Type == TokenType.AttributeName) { if (attrib.ValueToken.HasValue) { TextChange tc = new TextChange (currentToken.Start, currentToken.Length, selectedSugg); update (tc); SelectionStart = lines.GetLocation (attrib.ValueToken.Value.Start + tc.CharDiff + 1); CurrentLoc = lines.GetLocation (attrib.ValueToken.Value.End + tc.CharDiff - 1); } else { - update (new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\"")); - MoveLeft (); + update (new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\""), -1); + } + } else { + int offset = 1; + if (!attrib.ValueCloseToken.HasValue) { + selectedSugg += attrib.ValueCloseToken.Value.AsString(_text); + offset = 0; } + if (currentToken.Type == TokenType.AttributeValueOpen) + update (new TextChange (currentToken.End, 0, selectedSugg), offset); + else if (currentToken.Type == TokenType.AttributeValue) + update (new TextChange (currentToken.Start, currentToken.Length, selectedSugg), offset); + } + } else if (currentToken.Type == TokenType.ElementOpen) { + update (new TextChange (currentToken.End, 0, selectedSugg + " ")); } else update (new TextChange (currentToken.Start, currentToken.Length, selectedSugg)); hideOverlay (); @@ -255,7 +288,11 @@ namespace Crow case Key.Tab: case Key.Enter: case Key.KeypadEnter: - completeToken (); + string selectedSugg = overlay.SelectedItem is MemberInfo mi ? + mi.Name : overlay.SelectedItem?.ToString (); + if (selectedSugg == null) + break; + completeToken (selectedSugg); return; } } else if (e.Key == Key.Space && IFace.Ctrl) { @@ -346,8 +383,7 @@ namespace Crow selStart = SelectionStart.Value; selEnd = CurrentLoc.Value; } - } else - IFace.forceTextCursor = true; + } //} double spacePixelWidth = gr.TextExtents (" ").XAdvance; @@ -409,7 +445,7 @@ namespace Crow int size = buff.Length * 4 + 1; if (bytes.Length < size) - bytes = size > 512 ? new byte[size] : stackalloc byte[size]; + bytes = new byte[size]; int encodedBytes = buff.ToUtf8 (bytes); @@ -454,7 +490,7 @@ namespace Crow buff = sourceBytes.Slice(lines[i].Start, lines[i].Length); int size = buff.Length * 4 + 1; if (bytes.Length < size) - bytes = size > 512 ? new byte[size] : stackalloc byte[size]; + bytes = new byte[size]; int encodedBytes = buff.ToUtf8 (bytes); diff --git a/Samples/common/src/ImlParsing/Syntax.cs b/Samples/common/src/ImlParsing/Syntax.cs index ddbc6a92..6a839e6e 100644 --- a/Samples/common/src/ImlParsing/Syntax.cs +++ b/Samples/common/src/ImlParsing/Syntax.cs @@ -13,7 +13,8 @@ namespace Crow : base (message, innerException) { Token = token; } - } + public override string ToString() => $"{Message}: {Token.ToString()}"; + } public class SyntaxAnalyser { XmlSource source; IEnumerable<Token> tokens => source.Tokens; diff --git a/Samples/common/src/ImlParsing/Tokenizer.cs b/Samples/common/src/ImlParsing/Tokenizer.cs index 1ed08e5c..78791fe5 100644 --- a/Samples/common/src/ImlParsing/Tokenizer.cs +++ b/Samples/common/src/ImlParsing/Tokenizer.cs @@ -30,7 +30,7 @@ namespace Crow void skipWhiteSpaces (ref SpanCharReader reader) { while(!reader.EndOfSpan) { - switch (reader.Peak) { + switch (reader.Peek) { case '\x85': case '\x2028': case '\xA': @@ -46,7 +46,7 @@ namespace Crow case '\x20': case '\x9': char c = reader.Read(); - while (reader.TryPeak (c)) + while (reader.TryPeek (c)) reader.Read(); addTok (ref reader, c == '\x20' ? TokenType.WhiteSpace : TokenType.Tabulation); break; @@ -58,10 +58,10 @@ namespace Crow bool readName (ref SpanCharReader reader) { if (reader.EndOfSpan) return false; - char c = reader.Peak; + char c = reader.Peek; if (char.IsLetter(c) || c == '_' || c == ':') { reader.Advance (); - while (reader.TryPeak (ref c)) { + while (reader.TryPeek (ref c)) { if (!(char.IsLetterOrDigit(c) || c == '.' || c == '-' || c == '\xB7')) return true; reader.Advance (); @@ -92,25 +92,25 @@ namespace Crow if (reader.EndOfSpan) break; - switch (reader.Peak) { + switch (reader.Peek) { case '<': reader.Advance (); - if (reader.TryPeak ('?')) { + if (reader.TryPeek ('?')) { reader.Advance (); addTok (ref reader, TokenType.PI_Start); readName (ref reader); addTok (ref reader, TokenType.PI_Target); curState = States.ProcessingInstrucitons; - } else if (reader.TryPeak ('!')) { + } else if (reader.TryPeek ('!')) { reader.Advance (); - if (reader.TryPeak ("--")) { + if (reader.TryPeek ("--")) { reader.Advance (2); addTok (ref reader, TokenType.BlockCommentStart); if (reader.TryReadUntil ("-->")) { addTok (ref reader, TokenType.BlockComment); reader.Advance (3); addTok (ref reader, TokenType.BlockCommentEnd); - } else if (reader.TryPeak ("-->")) { + } else if (reader.TryPeek ("-->")) { reader.Advance (3); addTok (ref reader, TokenType.BlockCommentEnd); } @@ -121,12 +121,12 @@ namespace Crow curState = States.DTDObject; } } - } else if (reader.TryPeak('/')) { + } else if (reader.TryPeek('/')) { reader.Advance (); addTok (ref reader, TokenType.EndElementOpen); if (readName (ref reader)) { addTok (ref reader, TokenType.ElementName); - if (reader.TryPeak('>')) { + if (reader.TryPeek('>')) { reader.Advance (); addTok (ref reader, TokenType.ClosingSign); @@ -146,7 +146,7 @@ namespace Crow break; case '?': reader.Advance (); - if (reader.TryPeak ('>')){ + if (reader.TryPeek ('>')){ reader.Advance (); addTok (ref reader, TokenType.PI_End); }else diff --git a/Samples/common/src/SampleBase.cs b/Samples/common/src/SampleBase.cs index 2ae28cb5..93526308 100644 --- a/Samples/common/src/SampleBase.cs +++ b/Samples/common/src/SampleBase.cs @@ -18,10 +18,11 @@ namespace Samples { public class SampleBase : Interface { - public SampleBase(IntPtr hWin) : base(800, 600, hWin) { } - public SampleBase() : base (800, 600, false) { } + public SampleBase(IntPtr hWin) : base(Configuration.Global.Get<int>("MainWinWidth", 800), Configuration.Global.Get<int>("MainWinHeight", 600), hWin) { } + public SampleBase() : base (Configuration.Global.Get<int>("MainWinWidth", 800), Configuration.Global.Get<int>("MainWinHeight", 600), true) { } public Version CrowVersion => Assembly.GetAssembly(typeof(Widget)).GetName().Version; + public Container crowContainer; static void showMsgBox (object sender) { Widget w = sender as Widget; @@ -60,9 +61,11 @@ namespace Samples new KeyBinding (Key.F1, Modifier.Super), new Binding<bool> ("CanExecute")); Commands = new CommandGroup("commands msg boxes", - new ActionCommand("Action 1", () => MessageBox.ShowModal(this, MessageBox.Type.Information, "context menu 1 clicked")), - new ActionCommand("Action two", () => MessageBox.ShowModal(this, MessageBox.Type.Information, "context menu 2 clicked"), null, false), - new ActionCommand("Action three", () => MessageBox.ShowModal(this, MessageBox.Type.Information, "context menu 3 clicked")) + new ActionCommand("Action 1", () => MessageBox.ShowModal(this, MessageBox.Type.Information, "context menu 1 clicked"), "#Icons.gavel.svg" ), + new ActionCommand("Action two", () => MessageBox.ShowModal(this, MessageBox.Type.Information, "context menu 2 clicked"), "#Icons.compile.svg", false), + new ActionCommand("Action three", () => MessageBox.ShowModal(this, MessageBox.Type.Information, "context menu 3 clicked"), "#Icons.calendar.svg"), + CMDToggleBoolVal, + CMDHosted ); AllCommands = new CommandGroup ("All Commands", FileCommands, @@ -70,6 +73,19 @@ namespace Samples new CommandGroup ("Combined commands", FileCommands, EditCommands), new ActionCommand("Action A", () => MessageBox.ShowModal(this, MessageBox.Type.Information, "context menu A clicked")) ); + + CMDObsListAdd = new ActionCommand ("Add", + () => { + ObservableTestList.Add(obsListNewItem); + ObsListNewItem = null; + },null, !string.IsNullOrEmpty(obsListNewItem)); + CMDObsListRemove= new ActionCommand ("Remove", + () => { + ListBox lb = crowContainer.FindByName("lb") as ListBox; + string selItem = lb?.SelectedItem as string; + if (!string.IsNullOrEmpty(selItem)) + ObservableTestList.Remove(lb.SelectedItem as string); + },null, true); } DeviceEventType deviceEventTypeEnum; public DeviceEventType DeviceEventTypeEnum { @@ -316,10 +332,26 @@ namespace Samples } } + public ActionCommand CMDObsListAdd,CMDObsListRemove; + string obsListNewItem = "new item"; + public string ObsListNewItem { + get => obsListNewItem; + set { + if (string.Equals(obsListNewItem, value)) + return; + obsListNewItem = value; + NotifyValueChanged(obsListNewItem); + CMDObsListAdd.CanExecute = !string.IsNullOrEmpty(obsListNewItem); + } + } + public ObservableList<string> ObservableTestList = new ObservableList<string>(new string[]{"string1", "string2"}); + IList<Colors> testList = (IList<Colors>)EnumsNET.Enums.GetValues<Colors>().ToList();//.ColorDic.Values//.OrderBy(c=>c.Hue) //.ThenBy(c=>c.Value).ThenBy(c=>c.Saturation) //.ToList (); + public IList<DbgEvtType> AvailaibleDbgEvents => EnumsNET.Enums.GetValues<DbgEvtType>().ToList(); + public DbgEvtType TestDbgEventSelect; public IList<Colors> TestList { set @@ -332,6 +364,74 @@ namespace Samples void OnClear(object sender, MouseButtonEventArgs e) => TestList = null; void OnLoadList(object sender, MouseButtonEventArgs e) => TestList = (IList<Colors>)EnumsNET.Enums.GetValues<Colors>().ToList(); + #region logging tetsts + [Flags] + public enum LogType { + None = 0, + Low = 0x0001, + Normal = 0x0002, + High = 0x0004, + Message = Low | Normal | High, + Debug = 0x0008, + Warning = 0x0010, + Error = 0x0020, + WarnErr = Warning | Error, + Custom1 = 0x0040, + Custom2 = 0x0080, + Custom3 = 0x0100, + code = 0x1000, + crowEdit = 0x2000, + Plugin = 0x4000, + + + Custom = Custom1 | Custom2 | Custom3, + all = 0xffff + } + public class LogEntry { + public LogType Type; + public string msg; + public LogEntry (LogType type, string message) { + Type = type; + msg = message; + } + public override string ToString() => msg; + } + + public class LogItem { + public string Name; + public ObservableList<LogEntry> log; + public LogItem(string name) { + Name = name; + log = new ObservableList<LogEntry>(); + } + public void Add(LogType type, string message) { + lock (log) + log.Add (new LogEntry(type, message)); + } + public void ResetLog () { + lock (log) + log.Clear (); + } + + } + public ObservableList<LogItem> Logs = new ObservableList<LogItem>(new LogItem[]{new LogItem("CrowEdit")}); + public LogItem MainLog => Logs[0]; + [Obsolete]public void Log(LogType type, string message) { + MainLog.Add (type, message); + } + [Obsolete]public void ResetLog () { + MainLog.ResetLog(); + } + public LogItem GetLog(string name) { + LogItem li = Logs.FirstOrDefault(l=>string.Equals(l.Name,name,StringComparison.OrdinalIgnoreCase)); + if (li == null) { + li = new LogItem(name); + lock (Logs) + Logs.Add(li); + } + return li; + } + #endregion string curSources = ""; public bool boolVal = true, canExecute; @@ -384,13 +484,24 @@ namespace Samples protected override void OnInitialized() { initCommands(); + Log(LogType.Message, "test log"); + Log(LogType.Message, "test log2"); + Log(LogType.Message, "test log3"); + LogItem li = GetLog("new log"); + li.Add(LogType.Error, "smlkqjsflmkdsf"); + li.Add(LogType.Error, "smlkqj"); base.OnInitialized(); } protected override void processDrawing(IContext ctx) { base.processDrawing(ctx); } - + public override void ProcessResize(Rectangle bounds) + { + base.ProcessResize(bounds); + Configuration.Global.Set ("MainWinWidth", clientRectangle.Width); + Configuration.Global.Set ("MainWinHeight", clientRectangle.Height); + } public override bool OnKeyDown(KeyEventArgs e) { diff --git a/Samples/common/src/SampleBaseForEditor.cs b/Samples/common/src/SampleBaseForEditor.cs index 5c87226d..b97982e6 100644 --- a/Samples/common/src/SampleBaseForEditor.cs +++ b/Samples/common/src/SampleBaseForEditor.cs @@ -13,11 +13,16 @@ using System.Diagnostics; using Crow.Text; using System.Collections.Generic; using Encoding = System.Text.Encoding; +using System.Linq; namespace Samples { public class SampleBaseForEditor : SampleBase { + static SampleBaseForEditor() { + //DbgLogger.ConsoleOutput = !Configuration.Global.Get<bool> (nameof (DebugLogToFile)); + //RecordedEvents = Configuration.Global.Get<ObservableList<DbgEvtType>> ("RecordedEvents"); + } public static SampleBaseForEditor CurrentProgramInstance; protected override void OnInitialized () { @@ -32,7 +37,6 @@ namespace Samples protected const string _defaultFileName = "unnamed.txt"; protected string source = "", origSource; protected Editor editor; - bool debugLogRecording; public string CurrentDir { @@ -64,36 +68,23 @@ namespace Samples NotifyValueChanged ("IsDirty", IsDirty); } } + + #region DebugLog + bool debugLogRecording; public bool DebugLoggingEnabled => DbgLogger.IsEnabled; - /*public DbgEvtType RecordedEvents { - get => Configuration.Global.Get<DbgEvtType> (nameof (RecordedEvents)); - set { - if (RecordedEvents == value) - return; - Configuration.Global.Set (nameof (RecordedEvents), value); - if (DebugLogRecording) - DbgLogger.IncludeEvents = RecordedEvents; - NotifyValueChanged(RecordedEvents); - } - } - public DbgEvtType DiscardedEvents { - get => Configuration.Global.Get<DbgEvtType> (nameof (DiscardedEvents)); - set { - if (DiscardedEvents == value) - return; - Configuration.Global.Set (nameof (DiscardedEvents), value); - if (DebugLogRecording) - DbgLogger.DiscardEvents = DiscardedEvents; - NotifyValueChanged(DiscardedEvents); - } - }*/ + static ObservableList<DbgEvtType> RecordedEvents; public bool DebugLogRecording { get => debugLogRecording; set { if (debugLogRecording == value) return; debugLogRecording = value; + if (debugLogRecording) { + DbgLogger.IncludedEvents = new List<DbgEvtType>(RecordedEvents); + } else { + DbgLogger.IncludedEvents = null; + } NotifyValueChanged(debugLogRecording); } } @@ -116,10 +107,7 @@ namespace Samples NotifyValueChanged (DebugLogFilePath); } } - - protected static void initDebugLog () { - DbgLogger.ConsoleOutput = !Configuration.Global.Get<bool> (nameof (DebugLogToFile)); - } + #endregion public new bool IsDirty => source != origSource; @@ -274,7 +262,7 @@ namespace Samples resetUndoRedo (); } protected bool disableTextChangedEvent = false; - protected void apply (TextChange change) { + protected void apply (TextChange change, bool updateEditorPosition = true) { Span<char> tmp = stackalloc char[source.Length + (change.ChangedText.Length - change.Length)]; ReadOnlySpan<char> src = source.AsSpan (); src.Slice (0, change.Start).CopyTo (tmp); @@ -284,17 +272,18 @@ namespace Samples disableTextChangedEvent = true; Source = tmp.ToString (); disableTextChangedEvent = false; - editor.SelectionStart = null; - editor.SetCursorPosition (change.Start + change.ChangedText.Length); - - forceTextCursor = true; + if (updateEditorPosition) { + editor.SelectionStart = null; + editor.SetCursorPosition (change.Start + change.ChangedText.Length); + forceTextCursor(); + } } - protected void applyChange (TextChange change) { + protected void applyChange (TextChange change, bool updateEditorPosition = true) { undoStack.Push (change.Inverse (source)); redoStack.Clear (); CMDUndo.CanExecute = true; CMDRedo.CanExecute = false; - apply (change); + apply (change, updateEditorPosition); } public void goUpDirClick (object sender, MouseButtonEventArgs e) { @@ -326,7 +315,7 @@ namespace Samples protected void onTextChanged (object sender, TextChangeEventArgs e) { if (disableTextChangedEvent) return; - applyChange (e.Change); + applyChange (e.Change, false); } protected void textView_KeyDown (object sender, Crow.KeyEventArgs e) { if (Ctrl) { diff --git a/Samples/common/ui/Interfaces/Divers/0.crow b/Samples/common/ui/Interfaces/Divers/0.crow index b00da647..a00a5281 100644 --- a/Samples/common/ui/Interfaces/Divers/0.crow +++ b/Samples/common/ui/Interfaces/Divers/0.crow @@ -19,7 +19,7 @@ </ListBox> <Label Width="Stretched" Margin="3" Background="DimGrey" /> <TextBox Text="TextBox" Multiline="true" Margin="3" /> - <HorizontalStack Height="Fit" Margin="15" Background="Jet" CornerRadius="10"> + <HorizontalStack Height="Fit" Background="Jet" CornerRadius="10" Margin="5"> <VerticalStack Spacing="5" Width="50%"> <CheckBox Fit="true" Caption="test" /> <CheckBox Fit="true" /> @@ -37,8 +37,8 @@ <Label Text="MouseEvents" Width="50%" Margin="3" Focusable="true" Background="Jet" Foreground="DimGrey" TextAlignment="Center" MouseEnter="{Foreground=White}" MouseLeave="{Foreground=DimGrey}" MouseDown="{Background=DarkRed}" MouseClick="{Foreground=Green}" MouseDoubleClick="{Foreground=Yellow}" MouseUp="{Background=Jet}" /> <Label Text="MouseEvents" Width="50%" Margin="3" Background="Jet" Foreground="DimGrey" TextAlignment="Center" MouseClick="{Foreground=Green}" MouseDoubleClick="{Foreground=Yellow}" MouseEnter="{Foreground=White}" MouseLeave="{Foreground=DimGrey}" MouseDown="{Background=SeaGreen}" MouseUp="{Background=DimGrey}" /> </HorizontalStack> - <GroupBox Caption="Templated controls" Height="Fit" Margin="5"> - <HorizontalStack Height="Fit" Margin="10"> + <GroupBox Caption="Templated controls" Height="Fit" Margin="1"> + <HorizontalStack Height="Fit" > <VerticalStack Width="50%"> <CheckBox Style="CheckBox2" IsChecked="true" /> <CheckBox Style="CheckBox2" /> diff --git a/Samples/common/ui/Interfaces/Divers/2.crow b/Samples/common/ui/Interfaces/Divers/2.crow index 885c3ba0..9d31e65b 100644 --- a/Samples/common/ui/Interfaces/Divers/2.crow +++ b/Samples/common/ui/Interfaces/Divers/2.crow @@ -1,6 +1,6 @@ <?xml version="1.0"?> <VerticalStack Fit="true" Spacing="0"> - <TextBox Font="droid, 20" Text="multiline text box" Width="Stretched" Multiline="true"/> + <TextBox Font="mono, 20" Text="multiline text box" Width="Stretched" Multiline="true"/> <HorizontalStack Background="DarkSlateGrey" Margin="15" Spacing="15" Fit="true" MouseEnter="{Background=Jet}" MouseLeave="{Background=Grey}"> <TextBox Focusable="true" Text="left" Width="80" Height="30" TextAlignment="Left"/> <TextBox Focusable="true" Text="centered" Width="80" Height="30" TextAlignment="Center"/> diff --git a/Samples/common/ui/Interfaces/Divers/clip4.crow b/Samples/common/ui/Interfaces/Divers/clip4.crow index 5caaf771..9b89cfa9 100644 --- a/Samples/common/ui/Interfaces/Divers/clip4.crow +++ b/Samples/common/ui/Interfaces/Divers/clip4.crow @@ -2,31 +2,31 @@ <Border Fit="true" BorderWidth="2" > <Scroller CornerRadius="2" Height="200" Width="300" Background="DimGrey" Margin="2"> <VerticalStack Margin="10" VerticalAlignment="Top" Fit="true" Background="vgradient|0:RoyalBlue|1:Black" > - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 1"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 2"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 3"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 4"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 5"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 6"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 7"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 8"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 9"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 10"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 11"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 12"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 13"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 14"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 15"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 16"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 17"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 18"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 19"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 20"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 21"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 22"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 23"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 24"/> - <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="droid,20" Text="label 25"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 1"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 2"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 3"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 4"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 5"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 6"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 7"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 8"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 9"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 10"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 11"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 12"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 13"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 14"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 15"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 16"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 17"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 18"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 19"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 20"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 21"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 22"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 23"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 24"/> + <Label MouseEnter="{Background=Grey}" MouseLeave="{Background=hgradient|0:DarkRed|1:Transparent}" Margin="5" Background="hgradient|0:DarkRed|1:Transparent" Font="mono,20" Text="label 25"/> </VerticalStack> </Scroller> </Border> diff --git a/Samples/common/ui/Interfaces/Divers/colorsSyntaxing.crow b/Samples/common/ui/Interfaces/Divers/colorsSyntaxing.crow new file mode 100644 index 00000000..3fcfb68e --- /dev/null +++ b/Samples/common/ui/Interfaces/Divers/colorsSyntaxing.crow @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<Window Width="80%" Height="90%"> +<ListBox Name="ColorList" Data="{TestList}" Margin="5"> + <Template> + <Wrapper Name="ItemsContainer" Background="White"/> + </Template> + <ItemTemplate> + <VerticalStack Height="Fit" Width="200"> + <Label Text="private void + '" Font="mono, 16" Foreground="{}" Width="Stretched" /> + <Label Text="{}" Font="mono, 9" Foreground="LightGrey" HorizontalAlignment="Left" /> + </VerticalStack> + </ItemTemplate> + +</ListBox> +</Window> diff --git a/Samples/common/ui/Interfaces/Divers/fps.crow b/Samples/common/ui/Interfaces/Divers/fps.crow index 1d515a15..512dde67 100644 --- a/Samples/common/ui/Interfaces/Divers/fps.crow +++ b/Samples/common/ui/Interfaces/Divers/fps.crow @@ -5,7 +5,7 @@ <VerticalStack Fit="true" Name="vsFps" Spacing="10" > <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Margin="5" Name="labUpdate" Text="{update}" Font="droid,12" Background="SeaGreen" Width="50" TextAlignment="Center"/> + <Label Margin="5" Name="labUpdate" Text="{update}" Font="mono,12" Background="SeaGreen" Width="50" TextAlignment="Center"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Name="captionFps" Text="Fps:" Width="50" TextAlignment="Right"/> diff --git a/Samples/common/ui/Interfaces/Divers/newfile.crow b/Samples/common/ui/Interfaces/Divers/newfile.crow new file mode 100644 index 00000000..9554764b --- /dev/null +++ b/Samples/common/ui/Interfaces/Divers/newfile.crow @@ -0,0 +1,6 @@ +<Border Foreground="White" Fit="true"> + <VerticalStack> + <Label Text='Hello World' Background='MediumSeaGreen' Margin='0'/> + <Label Text='Hello World' Background='MediumSeaGreen' Margin='0'/> + </VerticalStack> +</Border>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Divers/observableList.crow b/Samples/common/ui/Interfaces/Divers/observableList.crow new file mode 100644 index 00000000..9caa0b43 --- /dev/null +++ b/Samples/common/ui/Interfaces/Divers/observableList.crow @@ -0,0 +1,17 @@ +<VerticalStack Margin="10"> + <TextBox Text="{²ObsListNewItem}"/> + <Label Name="curItem" Text="{../lb.SelectedItem}"/> + <HorizontalStack Height="Fit"> + <Button Command="{CMDObsListAdd}" /> + <Button Command="{CMDObsListRemove}" IsEnabled="{../lb.SelectionIsEmpty}" /> + </HorizontalStack> + <ListBox Name="lb" Data="{ObservableTestList}" > + <Template> + <Border Style="ControlBorder" MinimumSize="10,10" Background="{./Background}" CornerRadius="{./CornerRadius}"> + <Scroller Name="scroller1" > + <VerticalStack Height="Fit" Name="ItemsContainer" VerticalAlignment="Top"/> + </Scroller> + </Border> + </Template> + </ListBox> +</VerticalStack>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Divers/testImageUrl.crow b/Samples/common/ui/Interfaces/Divers/testImageUrl.crow new file mode 100644 index 00000000..802d8e1b --- /dev/null +++ b/Samples/common/ui/Interfaces/Divers/testImageUrl.crow @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<VerticalStack> + <Image Name="img" Width="Fit" Height="Fit" Background="vgradient|0:SkyBlue|1:White" Path="url:https://api.nuget.org/v3-flatcontainer/crow/1.2.0-beta/icon"/> + <Image Width="Fit" Height="Fit" Background="vgradient|0:SkyBlue|1:White" Path="url:https://api.nuget.org/v3-flatcontainer/csoft.crow/9.1.3/icon"/> + <Image Width="32" Height="32" Background="vgradient|0:SkyBlue|1:White" Path="url:https://api.nuget.org/v3-flatcontainer/vkcrowwindow/0.3.9/icon"/> + <Image Width="32" Height="32" Background="vgradient|0:SkyBlue|1:White" Path="url:https://api.nuget.org/v3-flatcontainer/leaf.xnet/5.2.10/icon"/> + <Label Text="{../img.Path}" Foreground="RebeccaPurple"/> +</VerticalStack>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Divers/testTextBox.crow b/Samples/common/ui/Interfaces/Divers/testTextBox.crow index 266eeebb..07156f26 100644 --- a/Samples/common/ui/Interfaces/Divers/testTextBox.crow +++ b/Samples/common/ui/Interfaces/Divers/testTextBox.crow @@ -6,15 +6,15 @@ <TextBox Background="DarkGrey" Width="50" TextAlignment="Right" Foreground="White"/> </HorizontalStack> - <TextBox Text="A\nBB\nCCC\nDDDD" Focused="true" Name="tb" Multiline="true" Font="droid,16" Margin="5" /> - <TextBox Multiline="true" Font="droid,16" Name="tb5" Margin="5" Text="{../tb.Selection}"/> - <TextBox Font="droid,10" Name="tb2" Margin="0" Text="this is a test of a text box"/> - <TextBox Font="droid,10" Name="tb3" Margin="5" Text="this is a test of a text box"/> - <TextBox Font="droid,10" Name="tb4" Margin="5" Text="this is a test of a text box"/> - <TextBox Font="droid,10" Name="tb5" Margin="20" Text="this is a test of a text box"/> - <TextBox Multiline="true" Font="droid,10" Name="tb6" Margin="5" Text="this is a test of a text box\nthis is a test of a text box"/> - <TextBox Multiline="true" Font="droid,10" Name="tb7" Margin="1" TextAlignment="Center" + <TextBox Text="A\nBB\nCCC\nDDDD" Focused="true" Name="tb" Multiline="true" Font="mono,16" Margin="5" /> + <TextBox Multiline="true" Font="mono,16" Name="tb5" Margin="5" Text="{../tb.Selection}"/> + <TextBox Font="mono,10" Name="tb2" Margin="0" Text="this is a test of a text box"/> + <TextBox Font="mono,10" Name="tb3" Margin="5" Text="this is a test of a text box"/> + <TextBox Font="mono,10" Name="tb4" Margin="5" Text="this is a test of a text box"/> + <TextBox Font="mono,10" Name="tb5" Margin="20" Text="this is a test of a text box"/> + <TextBox Multiline="true" Font="mono,10" Name="tb6" Margin="5" Text="this is a test of a text box\nthis is a test of a text box"/> + <TextBox Multiline="true" Font="mono,10" Name="tb7" Margin="1" TextAlignment="Center" Text="this is a test of a text boxthis is a test\nthis is a test when line are centered"/> - <TextBox Multiline="true" Font="droid,10" Name="tb8" Margin="1" TextAlignment="Center" + <TextBox Multiline="true" Font="mono,10" Name="tb8" Margin="1" TextAlignment="Center" Text="this is a test of a text box\n\n\nthis is a test\nthis is a test when line are centered"/> </VerticalStack>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Experimental/colorPicktest.crow b/Samples/common/ui/Interfaces/Experimental/colorPicktest.crow index 62ed8f7a..344cd5fb 100644 --- a/Samples/common/ui/Interfaces/Experimental/colorPicktest.crow +++ b/Samples/common/ui/Interfaces/Experimental/colorPicktest.crow @@ -12,7 +12,7 @@ Unselected="{Background=Transparent}"> <HorizontalStack Height="Fit" Spacing="10" > <Widget Width="60" Height="40" Background="{}" CornerRadius="3"/> - <Label Text="{}" Width="Stretched" Font="Mono, 20" /> + <Label Text="{}" Width="Stretched" Font="Mono, 12" /> </HorizontalStack> </ListItem> </ItemTemplate> diff --git a/Samples/common/ui/Interfaces/Experimental/tabviewLog.crow b/Samples/common/ui/Interfaces/Experimental/tabviewLog.crow new file mode 100644 index 00000000..8ac2447b --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/tabviewLog.crow @@ -0,0 +1,31 @@ +<TabView Orientation="Horizontal" Data="{Logs}"> + <Template> + <GenericStack Orientation="{./OppositeOrientation}" Spacing="0" Background="{./Background}"> + <ListBox Data="{./Items}" Fit="true" HorizontalAlignment="Left" VerticalAlignment="Top" SelectedItem="{²./SelectedItem}"> + <Template> + <GenericStack Orientation="{../../../Orientation}" Name="ItemsContainer" /> + </Template> + <ItemTemplate> + <ListItem Fit="true" Background="${InactiveTabItem}" IsSelected="{IsVisible}" Margin="5" + Selected="{.DataSource.Visible='true'};{Background=.DataSource.Background}" + Unselected="{.DataSource.Visible='false'};{Background=${InactiveTabItem}}"> + <Label Text="{Name}" /> + </ListItem> + </ItemTemplate> + </ListBox> + <Group Name="ItemsContainer" /> + </GenericStack> + </Template> + <ItemTemplate> + <ListItem IsVisible='{IsSelected}' IsSelected='{²IsSelected}'> + <VerticalStack> + <Label Text="{Name}"/> + <ListBox Data="{log}"> + <ItemTemplate> + <Label Text="{msg}"/> + </ItemTemplate> + </ListBox> + </VerticalStack> + </ListItem> + </ItemTemplate> +</TabView>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Experimental/tabviewLog2.crow b/Samples/common/ui/Interfaces/Experimental/tabviewLog2.crow new file mode 100644 index 00000000..6bcf628e --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/tabviewLog2.crow @@ -0,0 +1,74 @@ + <TabView Data="{Logs}"> + <Template> + <VerticalStack Spacing="0" > + <ListBox Data="{./Items}" Height="Fit" > + <Template> + <VerticalStack Spacing="0" > + <ScrollBar Orientation="Horizontal" Foreground="RoyalBlue" Height="6" Width="Stretched" CornerRadius="3" + Value="{²../ItemsScroller.ScrollX}" + LargeIncrement="{../ItemsScroller.PageWidth}" SmallIncrement="1" + CursorRatio="{../ItemsScroller.ChildWidthRatio}" Maximum="{../ItemsScroller.MaxScrollX}"> + <Template> + <Container Margin="1" Background="{./Background}"> + <Widget Name="Cursor" Background="{./Foreground}" CornerRadius="{./CornerRadius}"/> + </Container> + </Template> + </ScrollBar> + <Scroller Name="ItemsScroller" Height="Fit" Width="Stretched"> + <HorizontalStack Name="ItemsContainer" Width="Fit" HorizontalAlignment="Left"/> + </Scroller> + </VerticalStack> + </Template> + <ItemTemplate> + <ListItem RootDataLevel="true" Fit="true" Background="${InactiveTabBackground}" Foreground="${InactiveTabForeground}" IsSelected="{IsVisible}" + Selected="{.DataSource.IsVisible='true'};{Background=${SelectedTabBackground}};{Foreground=${SelectedTabForeground}}" + Unselected="{.DataSource.IsVisible='false'};{Background=${InactiveTabBackground}};{Foreground=${InactiveTabForeground}}" + BubbleEvents="MouseWheel"> + <HorizontalStack DataSource="{DataSource}" Margin="3" Spacing="5"> + <!--<Image Style="TreeIcon" Path="{Icon}" SvgSub="{IconSub}"/> No icon in Document class--> + <Label Text="{Name}" ContextCommands="{TabCommands}" Foreground="{../../Foreground}" /> + <Border CornerRadius="5" BorderWidth="1" Foreground="Transparent" Height="12" Width="12" + MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}"> + <Image Focusable="true" Name="Image" Margin="0" Width="Stretched" Height="Stretched" Path="#Crow.Icons.exit2.svg" + MouseClick="OnQueryClose"/> + </Border> + </HorizontalStack> + </ListItem> + </ItemTemplate> + </ListBox> + <Group Name="ItemsContainer" /> + </VerticalStack> + </Template> + <ItemTemplate> + <ListItem IsVisible="{IsSelected}" IsSelected="{²IsSelected}"> + <VerticalStack RootDataLevel="true" > + <HorizontalStack Height="Fit" Spacing="2" Margin="1"> + <Label Text="{../../../Caption}" Fit="true" Foreground="DimGrey" Font="${SmallUIFont}"/> + <Widget Width="Stretched"/> + <EnumSelector Caption="Filter:" EnumValue="{²../../log.Filter}" /> + <TextBox Background="Grey" Foreground="Black" MinimumSize="100,1" Text="{²../../log.SearchString}" Width="40%" KeyDown="../../log.onSearch" Font="${SmallUIFont}"/> + <CheckBox Fit="true" Caption="Case Sensitive" IsChecked="{²../../log.CaseSensitiveSearch}" Font="${SmallUIFont}"/> + <CheckBox Fit="true" Caption="All Word" IsChecked="{²../../log.AllWordSearch}" Font="${SmallUIFont}"/> + + <Menu Style="DockWinTitleBarMenu" Data="{../../log.SearchCommands}" Fit="true" Background="Transparent"/> + + <ListBox Style="DockWinTitleBarIconMenu" Data="{./DockCommands}"/> + <ListBox Style="DockWinTitleBarIconMenu" Data="{./Commands}"/> + <!--<ListBox Data="{./DockCommands}" Fit="true"> + <Template> + <HorizontalStack Name="ItemsContainer" /> + </Template> + <ItemTemplate Path="#Crow.WindowButton.template"/> + </ListBox> + <ListBox Data="{./Commands}" Fit="true"> + <Template> + <HorizontalStack Name="ItemsContainer" /> + </Template> + <ItemTemplate Path="#Crow.WindowButton.template"/> + </ListBox>--> + </HorizontalStack> + <ListBox Data="{log}"/> + </VerticalStack> + </ListItem> + </ItemTemplate> + </TabView>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Experimental/testDbg.crow b/Samples/common/ui/Interfaces/Experimental/testDbg.crow new file mode 100644 index 00000000..e6bc0fa5 --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/testDbg.crow @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<ListBox Data="{AvailaibleDbgEvents}"> + <Template> + <Wrapper Name="ItemsContainer"/> + </Template> + <ItemTemplate> + <ListItem Width="200" Selected="{lab.Background=RoyalBlue}"> + <Border Foreground="Transparent" MouseEnter="{Foreground=Grey}" MouseLeave="{Foreground=Transparent}"> + <Label Name="lab" Text="{}" Width="Stretched"/> + </Border> + </ListItem> + </ItemTemplate> +</ListBox> diff --git a/Samples/common/ui/Interfaces/Experimental/testDbgSelector.crow b/Samples/common/ui/Interfaces/Experimental/testDbgSelector.crow new file mode 100644 index 00000000..4e2792e0 --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/testDbgSelector.crow @@ -0,0 +1,18 @@ +<VerticalStack> + <Label Text="{TestDbgEventSelect}"/> + <EnumSelector Caption="Device Events:" EnumValue="{²TestDbgEventSelect}" ItemStyle="CheckBox2" Width="Fit" Background="Jet"> + <Template> + <Border Style="ControlBorder" Background="{./Background}" CornerRadius="{./CornerRadius}"> + <HorizontalStack> + <Label Text="{./Caption}"/> + <Popper Caption="{./EnumValue}" PopDirection="Bottom" > + <Template> + <Label Text="{./Caption}" Foreground="{./Foreground}" Width="200" /> + </Template> + <Wrapper Width="Fit" Height="400" Name="Content" Background="Onyx" Margin="5" Orientation="Horizontal"/> + </Popper> + </HorizontalStack> + </Border> + </Template> + </EnumSelector> +</VerticalStack> diff --git a/Samples/common/ui/Interfaces/Experimental/testDock.crow b/Samples/common/ui/Interfaces/Experimental/testDock.crow index 14659f88..78d8f138 100644 --- a/Samples/common/ui/Interfaces/Experimental/testDock.crow +++ b/Samples/common/ui/Interfaces/Experimental/testDock.crow @@ -1,8 +1,10 @@ <?xml version="1.0"?> -<DockStack Name="mainDock" Background="Jet" Margin="0"> - <DockWindow Resizable = "true" Top="100" Left="100" Caption="View 1" Width="300" Height="300"/> +<Group> +<DockWindow Style="DockWinSimple" Top="100" Left="100" Caption="View 1" Width="300" Height="300"/> +<DockStack Width="50%" Name="mainDock" Background="Jet" Margin="0"> + </DockStack> - +</Group> <!--- <DockWindow Left="450" Top="450" Width="150" Height="150" Background="Yellow"/>--> diff --git a/Samples/common/ui/Interfaces/Experimental/toolbox.crow b/Samples/common/ui/Interfaces/Experimental/toolbox.crow new file mode 100644 index 00000000..2ab83d1b --- /dev/null +++ b/Samples/common/ui/Interfaces/Experimental/toolbox.crow @@ -0,0 +1,24 @@ +<DockWindow Height="Fit" Width="Fit"> + <Template> + <Border Background="{./Background}" Margin="5" CornerRadius="0"> + <HorizontalStack> + <Widget Width="12" Height="Stretched" Background="Onyx" Name="MoveHandle" Focusable="true" CornerRadius="5"/> + <Container Name="Content" Width="Stretched"/> + </HorizontalStack> + </Border> + </Template> + <ListBox Data="{Commands}" Fit="true"> + <Template> + <HorizontalStack Name="ItemsContainer" Spacing="5" /> + </Template> + <ItemTemplate> + <Button Command="{}" MinimumSize="1,1" Width="40" Height="40" Background="vgradient|0:DimGrey|1:Black" CornerRadius="0" > + <Template> + <Border Style="ButtonBorder" Width="Stretched" Height="Stretched" Margin="10" Background="{./Background}" CornerRadius="{../CornerRadius}"> + <Image Path="{./Icon}" Tooltip="{./Caption}" Scaled="true" KeepProportions="true" Margin="0"/> + </Border> + </Template> + </Button> + </ItemTemplate> + </ListBox > +</DockWindow>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/TemplatedContainer/testWindow.goml b/Samples/common/ui/Interfaces/TemplatedContainer/testWindow.goml index e42a5c9f..70bcb873 100644 --- a/Samples/common/ui/Interfaces/TemplatedContainer/testWindow.goml +++ b/Samples/common/ui/Interfaces/TemplatedContainer/testWindow.goml @@ -28,17 +28,17 @@ <VerticalStack Fit="true" Name="vsFps" Spacing="10" > <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:SeaGreen|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Clipping:" Width="50" TextAlignment="Right"/> - <Label Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:SeaGreen|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:SeaGreen|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -61,7 +61,7 @@ </Border> <HorizontalStack Fit="true" Background="RoyalBlue" Margin="3"> <Widget Margin="10" Background="LimeGreen" Width="5" Height="5"/> - <TextBox Font="droid, 16" Multiline="true" Text="this is a test\nmultiline" Margin="2"/> + <TextBox Font="mono, 16" Multiline="true" Text="this is a test\nmultiline" Margin="2"/> <Widget Margin="10" Background="LimeGreen" Width="5" Height="5"/> </HorizontalStack> </VerticalStack> diff --git a/Samples/common/ui/Interfaces/TemplatedControl/testButton.crow b/Samples/common/ui/Interfaces/TemplatedControl/testButton.crow index 8911619d..1ef62eef 100644 --- a/Samples/common/ui/Interfaces/TemplatedControl/testButton.crow +++ b/Samples/common/ui/Interfaces/TemplatedControl/testButton.crow @@ -3,8 +3,8 @@ <HorizontalStack Fit="True"> <Button Caption="but" MouseClick="onButClick"/> <Button Caption="but" MouseClick="onButClick" Fit="true"/> - <Button Width="60" Height="40" MouseClick="onButClick"/> + <Button MouseClick="onButClick"/> <Button Caption="Long text button" MouseClick="onButClick"/> - <Button Font="droid, 20" Caption="Button"/> + <Button Font="mono, 12" Caption="Button"/> </HorizontalStack> </VerticalStack>
\ No newline at end of file diff --git a/Samples/common/ui/Interfaces/Widget/4.crow b/Samples/common/ui/Interfaces/Widget/4.crow index 81d386c9..15d602bb 100644 --- a/Samples/common/ui/Interfaces/Widget/4.crow +++ b/Samples/common/ui/Interfaces/Widget/4.crow @@ -4,22 +4,22 @@ <ProgressBar CornerRadius="5" Background="DimGrey" Margin="1" Maximum="1000" Value="{fps}" Width="200" Height="15"/> <HorizontalStack Fit="true"> <Label Text="Memory:" Width="50" TextAlignment="Right"/> - <Label Text="{memory}" Font="droid,12" TextAlignment="Center" + <Label Text="{memory}" Font="mono,12" TextAlignment="Center" Background="vgradient|0:Blue|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -39,17 +39,17 @@ </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -69,17 +69,17 @@ </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -101,17 +101,17 @@ <VerticalStack Fit="true" Name="vsFps" Spacing="10" > <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -131,17 +131,17 @@ </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -161,17 +161,17 @@ </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -193,17 +193,17 @@ <VerticalStack Fit="true" Name="vsFps" Spacing="10" > <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -223,17 +223,17 @@ </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -253,17 +253,17 @@ </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -285,17 +285,17 @@ <VerticalStack Fit="true" Name="vsFps" Spacing="10" > <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -315,17 +315,17 @@ </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> @@ -345,17 +345,17 @@ </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Update:" Width="50" TextAlignment="Right"/> - <Label Name="labUpdate" Text="{update}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labUpdate" Text="{update}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Layouting:" Width="50" TextAlignment="Right"/> - <Label Name="labLayouting" Text="{layouting}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labLayouting" Text="{layouting}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> <Label Text="Drawing:" Width="50" TextAlignment="Right"/> - <Label Name="labDrawing" Text="{drawing}" Font="droid,12" Width="80" TextAlignment="Center" + <Label Name="labDrawing" Text="{drawing}" Font="mono,12" Width="80" TextAlignment="Center" Background="vgradient|0:Green|1:Black"/> </HorizontalStack> <HorizontalStack Fit="true"> diff --git a/Samples/common/ui/templates/dockwinsimple.itmp b/Samples/common/ui/templates/dockwinsimple.itmp new file mode 100644 index 00000000..fa0e27e7 --- /dev/null +++ b/Samples/common/ui/templates/dockwinsimple.itmp @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<VerticalStack CacheEnabled="false" Name="MoveHandle" Background="{./Background}"> + <Label CacheEnabled="false" Background="Jet" Text="{./DockingPosition}"/> +</VerticalStack> |