public void RestoreTransformations()
=> NativeMethods.cairo_set_matrix (handle, ref savedMat);
public void SetSource(IPattern pat) => NativeMethods.cairo_set_source (handle, (pat as Pattern).handle);
- public void SetSource(ISurface surf, double x = 0, double y = 0)
- => NativeMethods.cairo_set_source_surface (handle, (surf as Surface).handle, x, y);
+ public async void SetSource(ISurface surf, double x = 0, double y = 0) {
+ NativeMethods.cairo_set_source_surface (handle, surf.Handle, x, y);
+ }
}
}
{
public class EglBackend : CairoBackendBase {
EGLDevice device;
+ GLSurface winSurf;
/// <summary>
/// Create a new generic backend bound to the application surface
/// </summary>
/// <param name="width">backend surface width</param>
/// <param name="height">backend surface height</param>
+ /// <param name="nativeWindoPointer"></param>
public EglBackend (int width, int height, IntPtr nativeWindoPointer)
: base (width, height, nativeWindoPointer) {
if (nativeWindoPointer == IntPtr.Zero) {
Glfw3.SwapInterval (0);
device = new EGLDevice (Glfw3.GetEGLDisplay (), Glfw3.GetEGLContext (hWin));
- surf = new GLSurface (device, Glfw3.GetEGLSurface (hWin), width, height);
+ //surf = new GLTextureSurface (device, width, height);
+ surf = new ImageSurface (Format.ARGB32, width, height);
+ winSurf = new GLSurface (device, Glfw3.GetEGLSurface (hWin), width, height);
}
/// <summary>
/// Create a new offscreen backend, used in perfTests
}
public override void FlushUIFrame(IContext ctx)
{
- base.FlushUIFrame (ctx);
- (surf as GLSurface).SwapBuffers ();
+ base.FlushUIFrame (ctx);
+ surf.Flush();
+ using (Context gr = new Context (winSurf)) {
+ gr.SetSource (surf);
+ gr.Paint();
+ }
+ winSurf.SwapBuffers ();
+ }
+ public override void ResizeMainSurface(int width, int height)
+ {
+ base.ResizeMainSurface(width, height);
+ winSurf?.Dispose();
+ winSurf = new GLSurface (device, Glfw3.GetEGLSurface (hWin), width, height);
}
}
}
base.FlushUIFrame (ctx);
}
+ public override void ResizeMainSurface(int width, int height)
+ {
+ if (surf is ImageSurface) {
+ surf?.Dispose();
+ surf = new ImageSurface (Format.ARGB32, width, height);
+ } else {
+ base.ResizeMainSurface(width, height);
+ }
+ }
}
}
public int Stride {
get { return NativeMethods.cairo_image_surface_get_stride (handle); }
}
+ public override void Resize(int width, int height)
+ {
+
+ }
}
}
public class Surface : ISurface
{
internal IntPtr handle = IntPtr.Zero;
+ public IntPtr Handle => handle;
+
protected Surface()
{
<ItemGroup>
<PackageReference Include="vke" Version="0.2.0-beta" />
- <PackageReference Include="vkvg.net" Version="0.5.0-beta" />
+ <PackageReference Include="vkvg.net" Version="0.6.0-beta" />
<ProjectReference Include="..\..\Drawing2D\Drawing2D.csproj" />
</ItemGroup>
protected Fence drawFence;
Surface surf;
Device vkvgDev;
- SampleCount samples = SampleCount.Sample_1;
+ SampleCount samples = SampleCount.Sample_8;
bool vsync = false;
bool tryGetPhy (vke.PhysicalDeviceCollection physicalDevices, VkPhysicalDeviceType phyType, out PhysicalDevice phy, bool swapchainSupport) {
new SvgHandle (vkvgDev, System.Text.Encoding.Unicode.GetBytes (svgFragment));
bool disposeContextOnFlush;
IRegion clipping;
+ volatile bool resizeMainSurface = false;
protected void clear(IContext ctx) {
for (int i = 0; i < clipping.NumRectangles; i++)
ctx.Rectangle (clipping.GetRectangle (i));
}
public override IContext PrepareUIFrame(IContext existingContext, IRegion clipping)
{
+ if (resizeMainSurface) {
+ createMainSurface (swapChain.Width, swapChain.Height);
+ clipping.UnionRectangle (new Rectangle(new Size((int)swapChain.Width, (int)swapChain.Height)));
+ resizeMainSurface = false;
+ }
this.clipping = clipping;
IContext ctx = existingContext;
if (ctx == null) {
{
if (disposeContextOnFlush)
ctx.Dispose ();
- clipping = null;
-
- dev.WaitIdle();
int idx = swapChain.GetNextImage ();
if (idx < 0) {
- createMainSurface (swapChain.Width, swapChain.Height);
+ resizeMainSurface = true;
return;
}
+ clipping = null;
+
+ //dev.WaitIdle();
+
drawFence.Wait ();
drawFence.Reset ();
graphicQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx], drawFence);
(graphicQueue as PresentQueue).Present (swapChain, drawComplete[idx]);
- dev.WaitIdle();
+ //dev.WaitIdle();
}
public override void ResizeMainSurface (int width, int height) {
//resize is done on swapchain image aquisition failure
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow.SkiaBackend", "Backends\SkiaBackend\Crow.SkiaBackend.csproj", "{ADAABC24-0152-41E2-BBEC-3AC9ACEE1175}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicTests", "Samples\BasicTests\BasicTests.csproj", "{1A0FF3B6-E97B-4F1D-9CDE-9C54742317BA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnimTest", "Samples\AnimTest\AnimTest.csproj", "{17DEFFB4-AA0C-4C92-999B-1F3DD4BB9AA1}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
{ADAABC24-0152-41E2-BBEC-3AC9ACEE1175}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADAABC24-0152-41E2-BBEC-3AC9ACEE1175}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADAABC24-0152-41E2-BBEC-3AC9ACEE1175}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1A0FF3B6-E97B-4F1D-9CDE-9C54742317BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A0FF3B6-E97B-4F1D-9CDE-9C54742317BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1A0FF3B6-E97B-4F1D-9CDE-9C54742317BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1A0FF3B6-E97B-4F1D-9CDE-9C54742317BA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {17DEFFB4-AA0C-4C92-999B-1F3DD4BB9AA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {17DEFFB4-AA0C-4C92-999B-1F3DD4BB9AA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {17DEFFB4-AA0C-4C92-999B-1F3DD4BB9AA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {17DEFFB4-AA0C-4C92-999B-1F3DD4BB9AA1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
{E06441A9-0CFD-45BB-9478-99D28CEB327F} = {451F5727-2A2E-4361-A41B-089429ADE8F9}
{34976828-80CF-4AC5-8C81-F66F635DC5FC} = {451F5727-2A2E-4361-A41B-089429ADE8F9}
{ADAABC24-0152-41E2-BBEC-3AC9ACEE1175} = {451F5727-2A2E-4361-A41B-089429ADE8F9}
+ {1A0FF3B6-E97B-4F1D-9CDE-9C54742317BA} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}
+ {17DEFFB4-AA0C-4C92-999B-1F3DD4BB9AA1} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {00D4E149-7131-49F4-BAAD-559AA961A78E}
Margin="0";
BubbleEvents="MouseWheel|Keyboard";
}
-TemplatedControl, GenericStack {
+TemplatedControl, GenericStack, Image {
CacheEnabled="true";
}
-<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg">
+<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<g id="False">
<rect height="9" width="9" y="0.5" x="0.5" stroke="#000" fill="#fff" stroke-width="1"/>-->
<line stroke-linecap="undefined" stroke-linejoin="undefined" x1="5" y1="2" x2="5" y2="8" stroke="#000" fill="none"/>
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg2"
- width="64"
- height="64"
viewBox="0 0 64 64"
version="1.1">
- <metadata
- id="metadata12">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs10" />
<g
id="True">
<circle
r="30"
cy="32"
cx="32"
- id="path4166"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.99999952;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="22"
cy="32"
cx="32"
- id="path4166-1"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.99999952;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1" />
</g>
<circle
<?xml version="1.0"?>
-<Border Background="{./Background}" Foreground="{./Foreground}"
- CornerRadius="{./CornerRadius}" BorderWidth="1">
- <HorizontalStack Spacing="0">
- <VerticalStack Margin="5">
- <SaturationValueSelector S="{²./S}" V="{²./V}" Focusable="true" Name="colorSelector" Margin="0"
- Foreground="{../hueSelector.HueColor}"
- Width="128" Height="128"/>
- <HueSelector Hue="{²./H}" Focusable="true" Name="hueSelector" Margin="0" Width="128" Height="20"/>
- </VerticalStack>
- <VerticalStack Margin="5" Spacing="1">
- <Widget Width="34" Height="21" Background="{./SelectedColor}"/>
- <Label Focusable="true" Selectable="true" Text="{./SelectedColor}" />
- <HorizontalStack Height="Fit">
- <Label Text="R" Width="Fit"/>
- <Spinner Style="ColorSpinner" Value="{²./R}" Width="46" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Text="G" Width="Fit"/>
- <Spinner Style="ColorSpinner" Value="{²./G}" Width="46" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Text="B" Width="Fit"/>
- <Spinner Style="ColorSpinner" Value="{²./B}" Width="46" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Text="A" Width="Fit"/>
- <Spinner Style="ColorSpinner" Value="{²./A}" Width="46" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Text="H" Width="Fit"/>
- <Spinner Style="HSVSpinner" Value="{²./H}" Width="46" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Text="S" Width="Fit"/>
- <Spinner Style="HSVSpinner" Value="{²./S}" Width="46" />
- </HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Text="V" Width="Fit"/>
- <Spinner Style="HSVSpinner" Value="{²./V}" Width="46" />
- </HorizontalStack>
- </VerticalStack>
- </HorizontalStack>
-</Border>
+<HueSelector Hue="{²./H}" Focusable="true" Name="hueSelector" Margin="0" Width="300" Height="50"/>
gr.Scale (widthRatio, heightRatio);
gr.Translate ((bounds.Width/widthRatio - Dimensions.Width)/2, (bounds.Height/heightRatio - Dimensions.Height)/2);
- using (ISurface imgSurf = iFace.Backend.CreateSurface (bounds.Width, bounds.Height)) {
+ using (ISurface imgSurf = iFace.Backend.CreateSurface (image, Dimensions.Width, Dimensions.Height)) {
gr.SetSource (imgSurf, 0,0);
gr.Paint ();
}
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);
/// backends are search where the main crow assembly is.
/// </summary>
public static string BackendsDirectory = null;
+ protected static Type getBackendType (IEnumerable<Type> backendTypes) {
+ if (backendTypes == null)
+ return null;
+ switch (PreferedBackendType) {
+ case BackendType.Default:
+ return backendTypes.FirstOrDefault(be => be.Name == "DefaultBackend");
+ case BackendType.Egl:
+ return backendTypes.FirstOrDefault(be => be.Name == "EglBackend");
+ case BackendType.Vulkan:
+ return backendTypes.FirstOrDefault(be => be.Name == "VulkanBackend");
+ case BackendType.Gl:
+ return backendTypes.FirstOrDefault(be => be.Name == "GlBackend");
+ default:
+ return backendTypes.FirstOrDefault();
+ }
+ }
protected static bool tryFindBackendType (out Type backendType) {
backendType = default;
- //IEnumerable<AssemblyName> backendAssemblies = Assembly.GetEntryAssembly ().GetReferencedAssemblies().Where (ra=>backends.Contains (ra.Name));
+ //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))) {
- IEnumerable<Type> backendTypes = a.ExportedTypes?.Where (e=>e.IsSubclassOf(typeof(CrowBackend)) && !e.IsAbstract);
- if (backendTypes != null) {
- backendType = backendTypes.FirstOrDefault();
+ backendType = getBackendType (a.ExportedTypes?.Where (e=>e.IsSubclassOf(typeof(CrowBackend)) && !e.IsAbstract));
+ if (backendType != null)
return true;
- }
}
+
string bp =
(!string.IsNullOrEmpty(BackendsDirectory) && Directory.Exists(BackendsDirectory)) ?
BackendsDirectory : Path.GetDirectoryName (Assembly.GetExecutingAssembly().Location);
+ //search backend directory
foreach (string b in backends) {
string bPath = Path.Combine (bp,$"Crow.{b}.dll");
if (File.Exists (bPath)) {
Assembly a = ldCtx.LoadFromAssemblyPath (bPath);
- IEnumerable<Type> backendTypes = a.ExportedTypes?.Where (e=>e.IsSubclassOf(typeof(CrowBackend)) && !e.IsAbstract);
- if (backendTypes != null) {
- if (PreferedBackendType == BackendType.Default)
- backendType = backendTypes.FirstOrDefault(be => be.Name == "DefaultBackend");
- else if (PreferedBackendType == BackendType.Egl)
- backendType = backendTypes.FirstOrDefault(be => be.Name == "EglBackend");
- else if (PreferedBackendType == BackendType.Vulkan)
- backendType = backendTypes.FirstOrDefault(be => be.Name == "VulkanBackend");
- else if (PreferedBackendType == BackendType.Gl)
- backendType = backendTypes.FirstOrDefault(be => be.Name == "GlBackend");
-
- if (backendType == null)
- backendType = backendTypes.FirstOrDefault();
- return backendType != null;
- }
+ backendType = getBackendType (a.ExportedTypes?.Where (e=>e.IsSubclassOf(typeof(CrowBackend)) && !e.IsAbstract));
+ return backendType != null;
}
}
Glfw3.SetCursorPosCallback (hWin, HandleCursorPosDelegate);
Glfw3.SetScrollCallback (hWin, HandleScrollDelegate);
Glfw3.SetCharCallback (hWin, HandleCharDelegate);
-#if !VKVG//resize is processed on context.Render failing
Glfw3.SetWindowSizeCallback (hWin, HandleWindowSizeDelegate);
-#endif
Glfw3.SetWindowRefreshCallback (hWin, HandleWindowRefreshDelegate);
}
/// <summary>
/// search for graphic object type in crow assembly, if not found,
/// search for type independently of namespace in all the loaded assemblies
- /// </summary>
+ /// </summary>
/// <remarks>
/// </remarks>
/// <returns>the corresponding type object</returns>
Terminate ();
}
public virtual void Terminate () {}
- public virtual void UpdateFrame () {}
+ int cpt;
+ public virtual void UpdateFrame () {
+ if (cpt++ > 1000) {
+ PerformanceMeasure.Notify ();
+ cpt=0;
+ }
+ }
public virtual void Quit () => Glfw3.SetWindowShouldClose (hWin, 1);
public bool Shift => Glfw3.GetKey(hWin, Key.LeftShift) == InputAction.Press ||
Monitor.Exit (UpdateMutex);
}
-
- PerformanceMeasure.Notify ();
}
/// <summary>Layouting loop, this is the first step of the udpate and process registered
/// Layouting queue items. Failing LQI's are requeued in this cycle until MaxTry is reached which
DbgLogger.StartEvent (DbgEvtType.MouseMove);
try {
+ Monitor.Enter (UpdateMutex);
int deltaX = x - MousePosition.X;
int deltaY = y - MousePosition.Y;
HoverOrDropTarget = null;
return false;
} finally {
+ Monitor.Exit (UpdateMutex);
DbgLogger.EndEvent (DbgEvtType.MouseMove);
}
}
DbgLogger.StartEvent (DbgEvtType.MouseDown);
try {
+ Monitor.Enter (UpdateMutex);
doubleClickTriggered = (lastMouseDown.ElapsedMilliseconds < DOUBLECLICK_TRESHOLD);
lastMouseDown.Restart ();
return true;
} finally {
+ Monitor.Exit (UpdateMutex);
DbgLogger.EndEvent (DbgEvtType.MouseDown);
}
}
DbgLogger.StartEvent (DbgEvtType.MouseUp);
try {
+ Monitor.Enter (UpdateMutex);
mouseRepeatTimer.Reset ();
lastMouseDownEvent = null;
return true;
} finally {
+ Monitor.Exit (UpdateMutex);
DbgLogger.EndEvent (DbgEvtType.MouseUp);
}
}
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
+using Drawing2D;
namespace Crow
{
RegisterForGraphicUpdate ();
}
}
-
+
public virtual double Hue {
get { return hue; }
set {
}
protected override void onDraw (IContext gr)
{
- base.onDraw (gr);
+ //base.onDraw (gr);
RectangleD r = ClientRectangle;
r.Height -= 4;
Gradient grad = new Gradient (
Orientation == Orientation.Vertical ? GradientType.Vertical : GradientType.Horizontal);
- grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 0, 0, 1)));
- grad.Stops.Add (new Gradient.ColorStop (0.167, new Color (1, 1, 0, 1)));
- grad.Stops.Add (new Gradient.ColorStop (0.333, new Color (0, 1, 0, 1)));
- grad.Stops.Add (new Gradient.ColorStop (0.5, new Color (0, 1, 1, 1)));
- grad.Stops.Add (new Gradient.ColorStop (0.667, new Color (0, 0, 1, 1)));
- grad.Stops.Add (new Gradient.ColorStop (0.833, new Color (1, 0, 1, 1)));
- grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, 0, 0, 1)));
+ grad.Stops.Add (new Gradient.ColorStop (0, new Color (1.0, 0.0, 0.0, 1.0)));
+ grad.Stops.Add (new Gradient.ColorStop (0.167, new Color (1.0, 1.0, 0.0, 1.0)));
+ grad.Stops.Add (new Gradient.ColorStop (0.333, new Color (0.0, 1.0, 0.0, 1.0)));
+ grad.Stops.Add (new Gradient.ColorStop (0.5, new Color (0.0, 1.0, 1.0, 1.0)));
+ grad.Stops.Add (new Gradient.ColorStop (0.667, new Color (0.0, 0.0, 1.0, 1.0)));
+ grad.Stops.Add (new Gradient.ColorStop (0.833, new Color (1.0, 0.0, 1.0, 1.0)));
+ grad.Stops.Add (new Gradient.ColorStop (1, new Color (1.0, 0.0, 0.0, 1.0)));
grad.SetAsSource (IFace, gr, r);
CairoHelpers.CairoRectangle (gr, r, CornerRadius);
r = ClientRectangle;
- switch (cursor) {
+ /*switch (cursor) {
case CursorType.Rectangle:
if (Orientation == Orientation.Horizontal) {
r.Width = 5;
gr.LineTo (r.Left, r.Bottom-0.5);
gr.LineTo (r.Left, y);
gr.ClosePath ();
- } else {
+ } else {
}
- break;
+ break;
}
gr.SetSource (Colors.Black);
gr.StrokePreserve ();
gr.SetSource (Colors.White);
gr.LineWidth = 1.0;
- gr.Stroke ();
+ gr.Stroke ();*/
}
public override void OnLayoutChanges (LayoutingType layoutType)
}
/// <summary>
/// Image file path, may be on disk or embedded. Accepts bitmaps or SVG drawings.
- /// </summary>
+ /// </summary>
public string Path {
get { return _pic == null ? "" : _pic.Path; }
set {
/// <summary>
/// Used only for svg images, repaint only node named referenced in SvgSub.
/// If null, all the svg is rendered
- /// </summary>
+ /// </summary>
public string SvgSub {
- get { return _svgSub; }
+ get => _svgSub;
set {
if (_svgSub == value)
return;
}
}
/// <summary>
- /// Object holding the image data once loaded, may be used directely to pupulate this control without
+ /// Object holding the image data once loaded, may be used directely to pupulate this control without
/// specifying a path.
- /// </summary>
+ /// </summary>
public Picture Picture {
get { return _pic; }
set {
/// <param name="layoutable">The children that is calling the constraints</param>
/// <param name="layoutType">The currently registering layouting types</param>
public virtual void ChildrenLayoutingConstraints(ILayoutable layoutable, ref LayoutingType layoutType){ }
- /// <summary> Query a layouting for the type pass as parameter, redraw only if layout changed. </summary>
internal ReaderWriterLockSlim layoutMutex = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
+ /// <summary> Query a layouting for the type pass as parameter, redraw only if layout changed. </summary>
public virtual void RegisterForLayouting(LayoutingType layoutType){
if (disposed) {
DbgLogger.AddEvent (DbgEvtType.AlreadyDisposed, this);
if (LayoutChanged != null)
LayoutChanged.Invoke (this, new LayoutingEventArgs (layoutType));
}
+ //Todo: is it necessary?? Raise method already check for null handler.
internal protected void raiseLayoutChanged(LayoutingType layoutingType){
if (LayoutChanged != null)
LayoutChanged.Raise (this, new LayoutingEventArgs(layoutingType));
<!-- 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>
void Clear ();
ISurface CreateSimilar (int width, int height);*/
void Resize (int width, int height);
+ IntPtr Handle { get; }
}
}
--- /dev/null
+<?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
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace vke
+{
+ public class AngleAnimation : FloatAnimation2
+ {
+ #region CTOR
+ public AngleAnimation(Object instance, string PropertyName, float Target, int stepCount = 20) :
+ base (instance,PropertyName,MathHelper.NormalizeAngle(Target),stepCount) {
+ initialValue = MathHelper.NormalizeAngle (initialValue);
+ }
+ #endregion
+ }
+}
+
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Diagnostics;
+
+namespace vke
+{
+ public delegate void AnimationEventHandler(Animation a);
+
+ public delegate float GetterDelegate();
+ public delegate void SetterDelegate(float value);
+
+ public class Animation
+ {
+ public event AnimationEventHandler AnimationFinished;
+
+ public static Random random = new Random ();
+ public static int DelayMs = 0;
+
+ protected GetterDelegate getValue;
+ protected SetterDelegate setValue;
+
+ public string propertyName;
+
+ protected Stopwatch timer = new Stopwatch();
+ protected int delayStartMs = 0;
+ /// <summary>
+ /// Delay before firing ZnimationFinished event.
+ /// </summary>
+ protected int delayFinishMs = 0;
+ public static List<Animation> AnimationList = new List<Animation>();
+ public static bool HasAnimations => AnimationList.Count > 0;
+ //public FieldInfo member;
+ public Object AnimatedInstance;
+
+ #region CTOR
+ public Animation (){}
+ public Animation(Object instance, string _propertyName)
+ {
+ propertyName = _propertyName;
+ AnimatedInstance = instance;
+ PropertyInfo pi = instance.GetType().GetProperty(propertyName);
+ try {
+ getValue = (GetterDelegate)Delegate.CreateDelegate(typeof(GetterDelegate), instance, pi.GetGetMethod());
+ setValue = (SetterDelegate)Delegate.CreateDelegate(typeof(SetterDelegate), instance, pi.GetSetMethod());
+ } catch (Exception ex) {
+ Debug.WriteLine (ex.ToString ());
+ }
+ }
+ #endregion
+
+ public static void StartAnimation(Animation a, int delayMs = 0, AnimationEventHandler OnEnd = null)
+ {
+ lock (AnimationList) {
+ Animation aa = null;
+ if (Animation.GetAnimation (a.AnimatedInstance, a.propertyName, ref aa)) {
+ aa.CancelAnimation ();
+ }
+
+ //a.AnimationFinished += onAnimationFinished;
+
+ a.AnimationFinished += OnEnd;
+ a.delayStartMs = delayMs + DelayMs;
+
+
+ if (a.delayStartMs > 0)
+ a.timer.Start ();
+
+ AnimationList.Add (a);
+ }
+
+ }
+
+ static Stack<Animation> anims = new Stack<Animation>();
+ static int frame = 0;
+ public static void ProcessAnimations()
+ {
+ frame++;
+
+// #region FLYING anim
+// if (frame % 20 == 0){
+// foreach (Player p in MagicEngine.CurrentEngine.Players) {
+// foreach (CardInstance c in p.InPlay.Cards.Where(ci => ci.HasAbility(AbilityEnum.Flying) && ci.z < 0.4f)) {
+//
+// }
+// }
+// }
+// #endregion
+ //Stopwatch animationTime = new Stopwatch();
+ //animationTime.Start();
+
+ const int maxAnim = 200000;
+ int count = 0;
+
+
+ lock (AnimationList) {
+ if (anims.Count == 0)
+ anims = new Stack<Animation> (AnimationList);
+ }
+
+ while (anims.Count > 0 && count < maxAnim) {
+ Animation a = anims.Pop ();
+ if (a == null)
+ continue;
+ if (a.timer.IsRunning) {
+ if (a.timer.ElapsedMilliseconds > a.delayStartMs)
+ a.timer.Stop ();
+ else
+ continue;
+ }
+
+ a.Process ();
+ count++;
+ }
+
+ //animationTime.Stop();
+ //Debug.WriteLine("animation: {0} ticks \t {1} ms ", animationTime.ElapsedTicks,animationTime.ElapsedMilliseconds);
+ }
+ public static bool GetAnimation(object instance, string PropertyName, ref Animation a)
+ {
+ for (int i = 0; i < AnimationList.Count; i++) {
+ Animation anim = AnimationList [i];
+ if (anim == null) {
+ continue;
+ }
+ if (anim.AnimatedInstance == instance && anim.propertyName == PropertyName) {
+ a = anim;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ public virtual void Process () {}
+ public void CancelAnimation()
+ {
+ //Debug.WriteLine("Cancel anim: " + this.ToString());
+ AnimationList.Remove(this);
+ }
+ public void RaiseAnimationFinishedEvent()
+ {
+ if (AnimationFinished != null)
+ AnimationFinished (this);
+ }
+
+ public static void onAnimationFinished(Animation a)
+ {
+ Debug.WriteLine ("\t\tAnimation finished: " + a.ToString ());
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using MiscUtil;
+using System.Reflection;
+
+namespace vke
+{
+ public class Animation<T> : Animation
+ {
+ public delegate T GetterDelegate();
+ public delegate void SetterDelegate(T value);
+
+ public T TargetValue;
+ T initialValue;
+ T zero;
+ public T Step;
+ public bool Cycle;
+
+ protected GetterDelegate getValue;
+ protected SetterDelegate setValue;
+
+ #region CTOR
+ public Animation(Object instance, string _propertyName)
+ {
+ propertyName = _propertyName;
+ AnimatedInstance = instance;
+ PropertyInfo pi = instance.GetType().GetProperty(propertyName);
+ getValue = (GetterDelegate)Delegate.CreateDelegate(typeof(GetterDelegate), instance, pi.GetGetMethod());
+ setValue = (SetterDelegate)Delegate.CreateDelegate(typeof(SetterDelegate), instance, pi.GetSetMethod());
+ }
+ public Animation(Object instance, string _propertyName, T Target, T step)
+ {
+ propertyName = _propertyName;
+ AnimatedInstance = instance;
+ PropertyInfo pi = instance.GetType().GetProperty(propertyName);
+ getValue = (GetterDelegate)Delegate.CreateDelegate(typeof(GetterDelegate), instance, pi.GetGetMethod());
+ setValue = (SetterDelegate)Delegate.CreateDelegate(typeof(SetterDelegate), instance, pi.GetSetMethod());
+
+ TargetValue = Target;
+
+ T value = getValue();
+ initialValue = value;
+ Type t = typeof(T);
+
+ if (t.IsPrimitive) {
+ Step = (T)Convert.ChangeType (step, t);
+ zero = (T)Convert.ChangeType (0, t);
+ }else {
+ Step = (T)Activator.CreateInstance (typeof(T), new Object[] { step });
+ zero = (T)Activator.CreateInstance (typeof(T), 0f);
+ }
+ T test = (T)Operator.SubtractAlternative (value, TargetValue);
+
+ if (Operator.LessThan(test, zero))
+ {
+ if (Operator.LessThan (Step, zero))
+ Step = Operator.Negate (Step);
+ }
+ else if (Operator.GreaterThan(Step, zero))
+ Step = Operator.Negate (Step);
+ }
+ #endregion
+
+ public override void Process()
+ {
+ T value = getValue();
+
+ //Debug.WriteLine ("Anim: {0} <= {1}", value, this.ToString ());
+
+ if (Operator.GreaterThan(Step, zero))
+ {
+ value = Operator.Add (value, Step);
+ setValue(value);
+ //Debug.WriteLine(value);
+ if (Operator.GreaterThan(Operator.Subtract(TargetValue, value), zero))
+ return;
+ }
+ else
+ {
+ value = Operator.Add (value, Step);
+ setValue(value);
+
+ if (Operator.LessThan(Operator.Subtract(TargetValue, value), zero))
+ return;
+ }
+
+ if (Cycle) {
+ Step = Operator.Negate (Step);
+ TargetValue = initialValue;
+ Cycle = false;
+ return;
+ }
+
+ setValue(TargetValue);
+ AnimationList.Remove(this);
+
+ RaiseAnimationFinishedEvent ();
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("{0}:->{1}:{2}",base.ToString(),TargetValue,Step);
+ }
+ }
+
+}
+
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Numerics;
+
+namespace vke
+{
+ public class BezierPath : Path
+ {
+ public Vector3 ControlPointStart;
+ public Vector3 ControlPointEnd;
+
+ public BezierPath (Vector3 startPos, Vector3 controlPointStart,
+ Vector3 controlPointEnd, Vector3 endPos)
+ :base(startPos, endPos)
+ {
+ ControlPointStart = controlPointStart;
+ ControlPointEnd = controlPointEnd;
+ }
+ public BezierPath (Vector3 startPos, Vector3 endPos, Vector3 vUp)
+ :base(startPos, endPos)
+ {
+ ControlPointStart = startPos + vUp;
+ ControlPointEnd = endPos + vUp;
+ }
+ public override Vector3 GetStep (float pos)
+ {
+ return Path.CalculateBezierPoint (pos, Start, ControlPointStart, ControlPointEnd, End);
+ }
+ }
+}
+
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace vke
+{
+ public class FloatAnimation : Animation
+ {
+
+ public float TargetValue;
+ float initialValue;
+ public float Step;
+ public bool Cycle;
+
+ #region CTOR
+ public FloatAnimation(Object instance, string _propertyName, float Target, float step = 0.2f)
+ : base(instance, _propertyName)
+ {
+
+ TargetValue = Target;
+
+ float value = getValue();
+ initialValue = value;
+
+ Step = step;
+
+ if (value < TargetValue)
+ {
+ if (Step < 0)
+ Step = -Step;
+ }
+ else if (Step > 0)
+ Step = -Step;
+ }
+ #endregion
+
+ public override void Process()
+ {
+ float value = getValue();
+
+ //Debug.WriteLine ("Anim: {0} <= {1}", value, this.ToString ());
+
+ if (Step > 0f)
+ {
+ value += Step;
+ setValue(value);
+ //Debug.WriteLine(value);
+ if (TargetValue > value)
+ return;
+ }
+ else
+ {
+ value += Step;
+ setValue(value);
+
+ if (TargetValue < value)
+ return;
+ }
+
+ if (Cycle) {
+ Step = -Step;
+ TargetValue = initialValue;
+ Cycle = false;
+ return;
+ }
+
+ setValue(TargetValue);
+ lock(AnimationList)
+ AnimationList.Remove(this);
+
+ RaiseAnimationFinishedEvent ();
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("{0}:->{1}:{2}",base.ToString(),TargetValue,Step);
+ }
+ }
+
+}
+
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace vke
+{
+ public class FloatAnimation2 : Animation
+ {
+
+ public float TargetValue;
+ protected float initialValue;
+ int stepCount, currentStep;
+
+ #region CTOR
+ public FloatAnimation2(Object instance, string _propertyName, float Target, int _stepCount = 20)
+ : base(instance, _propertyName)
+ {
+
+ TargetValue = Target;
+
+ float value = getValue();
+ initialValue = value;
+
+ stepCount = _stepCount;
+ }
+ #endregion
+
+ bool smooth = true;
+
+ float smoothedStep (float step) => (-MathF.Cos (step * MathF.PI) + 1)/2.0f;
+
+ public override void Process()
+ {
+
+ currentStep++;
+
+ float t = (float)currentStep / (float)stepCount;
+ if (smooth)
+ t = smoothedStep (t);
+
+ setValue (initialValue + t * (TargetValue - initialValue));
+
+ if (currentStep < stepCount)
+ return;
+
+ setValue(TargetValue);
+ AnimationList.Remove(this);
+ RaiseAnimationFinishedEvent ();
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("{0}:->{1}:{2}",base.ToString(),TargetValue,stepCount);
+ }
+ }
+
+}
+
--- /dev/null
+// Copyright (c) 2019-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+namespace vke {
+ public static class MathHelper {
+ public const float Pi = (float)Math.PI;
+ public const float TwoPi = (float)Math.PI * 2;
+ public static float NormalizeAngle (float a) {
+ float tmp = a % MathHelper.TwoPi;
+ if (tmp < 0)
+ tmp += MathHelper.TwoPi;
+ return tmp;
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System.Numerics;
+
+namespace vke {
+ public class Path
+ {
+ public Vector3 Start;
+ public Vector3 End;
+
+ float length;
+ Vector3 vDir;
+
+ public Path(Vector3 startPos, Vector3 endPos){
+ Start = startPos;
+ End = endPos;
+ initialComputations ();
+ }
+ protected void initialComputations(){
+ Vector3 vPath = End - Start;
+ vDir = Vector3.Normalize (vPath);
+ length = vPath.Length();
+ }
+ /// <summary>
+ /// Get single step on the path
+ /// </summary>
+ /// <returns>return position on the path</returns>
+ /// <param name="pos">Position expressed as percentage of total length</param>
+ public virtual Vector3 GetStep(float pos){
+ return Start + vDir * length * pos;
+ }
+
+ public static Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
+ {
+ float u = 1 - t;
+ float tt = t * t;
+ float uu = u * u;
+ float uuu = uu * u;
+ float ttt = tt * t;
+
+ Vector3 p = uuu * p0;
+ p += 3 * uu * t * p1;
+ p += 3 * u * tt * p2;
+ p += ttt * p3;
+
+ return p;
+ }
+ }
+
+}
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Numerics;
+
+namespace vke
+{
+ public class PathAnimation : Animation<Vector3>
+ {
+ Path path;
+ int stepCount, currentStep;
+
+ #region CTOR
+ public PathAnimation(Object instance, string _propertyName, Path _path, int _stepCount = 20)
+ : base(instance, _propertyName)
+ {
+ path = _path;
+ stepCount = _stepCount;
+ }
+
+ #endregion
+
+ bool smooth = true;
+
+ float smoothedStep (float step) => (-MathF.Cos (step * MathF.PI) + 1)/2.0f;
+
+ public override void Process()
+ {
+ currentStep++;
+
+ float t = (float)currentStep / (float)stepCount;
+ if (smooth)
+ t = smoothedStep (t);
+
+ Vector3 pos = path.GetStep (t);
+ setValue(pos);
+
+ if (currentStep < stepCount)
+ return;
+
+ AnimationList.Remove(this);
+ RaiseAnimationFinishedEvent ();
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("{0}:->{1}:{2}",base.ToString(),TargetValue,Step);
+ }
+ }
+}
+
--- /dev/null
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace vke
+{
+ public class ShakeAnimation : Animation
+ {
+ const float stepMin = 0.001f, stepMax = 0.005f;
+ bool rising = true;
+
+ public float LowBound;
+ public float HighBound;
+
+ #region CTOR
+ public ShakeAnimation(
+ Object instance,
+ string _propertyName,
+ float lowBound, float highBound)
+ : base(instance, _propertyName)
+ {
+
+ LowBound = Math.Min (lowBound, highBound);
+ HighBound = Math.Max (lowBound, highBound);
+
+ float value = getValue ();
+
+ if (value > HighBound)
+ rising = false;
+ }
+ #endregion
+
+ public override void Process ()
+ {
+ float value = getValue ();
+ float step = stepMin + (float)random.NextDouble () * stepMax;
+
+ if (rising) {
+ value += step;
+ if (value > HighBound) {
+ value = HighBound;
+ rising = false;
+ }
+ } else {
+ value -= step;
+ if (value < LowBound) {
+ value = LowBound;
+ rising = true;
+ } else if (value > HighBound)
+ value -= step * 10f;
+ }
+ setValue (value);
+ }
+
+ }
+
+}
+
--- /dev/null
+using System;
+using System.Linq.Expressions;
+
+namespace MiscUtil.Linq
+{
+ /// <summary>
+ /// General purpose Expression utilities
+ /// </summary>
+ public static class ExpressionUtil
+ {
+ /// <summary>
+ /// Create a function delegate representing a unary operation
+ /// </summary>
+ /// <typeparam name="TArg1">The parameter type</typeparam>
+ /// <typeparam name="TResult">The return type</typeparam>
+ /// <param name="body">Body factory</param>
+ /// <returns>Compiled function delegate</returns>
+ public static Func<TArg1, TResult> CreateExpression<TArg1, TResult>(
+ Func<Expression, UnaryExpression> body)
+ {
+ ParameterExpression inp = Expression.Parameter(typeof(TArg1), "inp");
+ try
+ {
+ return Expression.Lambda<Func<TArg1, TResult>>(body(inp), inp).Compile();
+ }
+ catch (Exception ex)
+ {
+ string msg = ex.Message; // avoid capture of ex itself
+ return delegate { throw new InvalidOperationException(msg); };
+ }
+ }
+
+ /// <summary>
+ /// Create a function delegate representing a binary operation
+ /// </summary>
+ /// <typeparam name="TArg1">The first parameter type</typeparam>
+ /// <typeparam name="TArg2">The second parameter type</typeparam>
+ /// <typeparam name="TResult">The return type</typeparam>
+ /// <param name="body">Body factory</param>
+ /// <returns>Compiled function delegate</returns>
+ public static Func<TArg1, TArg2, TResult> CreateExpression<TArg1, TArg2, TResult>(
+ Func<Expression, Expression, BinaryExpression> body)
+ {
+ return CreateExpression<TArg1, TArg2, TResult>(body, false);
+ }
+
+ /// <summary>
+ /// Create a function delegate representing a binary operation
+ /// </summary>
+ /// <param name="castArgsToResultOnFailure">
+ /// If no matching operation is possible, attempt to convert
+ /// TArg1 and TArg2 to TResult for a match? For example, there is no
+ /// "decimal operator /(decimal, int)", but by converting TArg2 (int) to
+ /// TResult (decimal) a match is found.
+ /// </param>
+ /// <typeparam name="TArg1">The first parameter type</typeparam>
+ /// <typeparam name="TArg2">The second parameter type</typeparam>
+ /// <typeparam name="TResult">The return type</typeparam>
+ /// <param name="body">Body factory</param>
+ /// <returns>Compiled function delegate</returns>
+ public static Func<TArg1, TArg2, TResult> CreateExpression<TArg1, TArg2, TResult>(
+ Func<Expression, Expression, BinaryExpression> body, bool castArgsToResultOnFailure)
+ {
+ ParameterExpression lhs = Expression.Parameter(typeof(TArg1), "lhs");
+ ParameterExpression rhs = Expression.Parameter(typeof(TArg2), "rhs");
+ try
+ {
+ try
+ {
+ return Expression.Lambda<Func<TArg1, TArg2, TResult>>(body(lhs, rhs), lhs, rhs).Compile();
+ }
+ catch (InvalidOperationException)
+ {
+ if (castArgsToResultOnFailure && !( // if we show retry
+ typeof(TArg1) == typeof(TResult) && // and the args aren't
+ typeof(TArg2) == typeof(TResult)))
+ { // already "TValue, TValue, TValue"...
+ // convert both lhs and rhs to TResult (as appropriate)
+ Expression castLhs = typeof(TArg1) == typeof(TResult) ?
+ (Expression)lhs :
+ (Expression)Expression.Convert(lhs, typeof(TResult));
+ Expression castRhs = typeof(TArg2) == typeof(TResult) ?
+ (Expression)rhs :
+ (Expression)Expression.Convert(rhs, typeof(TResult));
+
+ return Expression.Lambda<Func<TArg1, TArg2, TResult>>(
+ body(castLhs, castRhs), lhs, rhs).Compile();
+ }
+ else throw;
+ }
+ }
+ catch (Exception ex)
+ {
+ string msg = ex.Message; // avoid capture of ex itself
+ return delegate { throw new InvalidOperationException(msg); };
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+
+namespace MiscUtil
+{
+ interface INullOp<T>
+ {
+ bool HasValue(T value);
+ bool AddIfNotNull(ref T accumulator, T value);
+ }
+ sealed class StructNullOp<T>
+ : INullOp<T>, INullOp<T?>
+ where T : struct
+ {
+ public bool HasValue(T value)
+ {
+ return true;
+ }
+ public bool AddIfNotNull(ref T accumulator, T value)
+ {
+ accumulator = Operator<T>.Add(accumulator, value);
+ return true;
+ }
+ public bool HasValue(T? value)
+ {
+ return value.HasValue;
+ }
+ public bool AddIfNotNull(ref T? accumulator, T? value)
+ {
+ if (value.HasValue)
+ {
+ accumulator = accumulator.HasValue ?
+ Operator<T>.Add(
+ accumulator.GetValueOrDefault(),
+ value.GetValueOrDefault())
+ : value;
+ return true;
+ }
+ return false;
+ }
+ }
+ sealed class ClassNullOp<T>
+ : INullOp<T>
+ where T : class
+ {
+ public bool HasValue(T value)
+ {
+ return value != null;
+ }
+ public bool AddIfNotNull(ref T accumulator, T value)
+ {
+ if (value != null)
+ {
+ accumulator = accumulator == null ?
+ value : Operator<T>.Add(accumulator, value);
+ return true;
+ }
+ return false;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Linq.Expressions;
+using MiscUtil.Linq;
+
+namespace MiscUtil
+{
+ /// <summary>
+ /// The Operator class provides easy access to the standard operators
+ /// (addition, etc) for generic types, using type inference to simplify
+ /// usage.
+ /// </summary>
+ public static class Operator
+ {
+
+ /// <summary>
+ /// Indicates if the supplied value is non-null,
+ /// for reference-types or Nullable<T>
+ /// </summary>
+ /// <returns>True for non-null values, else false</returns>
+ public static bool HasValue<T>(T value)
+ {
+ return Operator<T>.NullOp.HasValue(value);
+ }
+ /// <summary>
+ /// Increments the accumulator only
+ /// if the value is non-null. If the accumulator
+ /// is null, then the accumulator is given the new
+ /// value; otherwise the accumulator and value
+ /// are added.
+ /// </summary>
+ /// <param name="accumulator">The current total to be incremented (can be null)</param>
+ /// <param name="value">The value to be tested and added to the accumulator</param>
+ /// <returns>True if the value is non-null, else false - i.e.
+ /// "has the accumulator been updated?"</returns>
+ public static bool AddIfNotNull<T>(ref T accumulator, T value)
+ {
+ return Operator<T>.NullOp.AddIfNotNull(ref accumulator, value);
+ }
+
+ /// <summary>
+ /// Evaluates unary negation (-) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T Negate<T>(T value)
+ {
+ return Operator<T>.Negate(value);
+ }
+ /// <summary>
+ /// Evaluates bitwise not (~) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T Not<T>(T value)
+ {
+ return Operator<T>.Not(value);
+ }
+ /// <summary>
+ /// Evaluates bitwise or (|) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T Or<T>(T value1, T value2)
+ {
+ return Operator<T>.Or(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates bitwise and (&) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T And<T>(T value1, T value2)
+ {
+ return Operator<T>.And(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates bitwise xor (^) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T Xor<T>(T value1, T value2)
+ {
+ return Operator<T>.Xor(value1, value2);
+ }
+ /// <summary>
+ /// Performs a conversion between the given types; this will throw
+ /// an InvalidOperationException if the type T does not provide a suitable cast, or for
+ /// Nullable<TInner> if TInner does not provide this cast.
+ /// </summary>
+ public static TTo Convert<TFrom, TTo>(TFrom value)
+ {
+ return Operator<TFrom, TTo>.Convert(value);
+ }
+ /// <summary>
+ /// Evaluates binary addition (+) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T Add<T>(T value1, T value2)
+ {
+ return Operator<T>.Add(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary addition (+) for the given type(s); this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static TArg1 AddAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
+ {
+ return Operator<TArg2, TArg1>.Add(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary subtraction (-) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T Subtract<T>(T value1, T value2)
+ {
+ return Operator<T>.Subtract(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary subtraction(-) for the given type(s); this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static TArg1 SubtractAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
+ {
+ return Operator<TArg2, TArg1>.Subtract(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary multiplication (*) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T Multiply<T>(T value1, T value2)
+ {
+ return Operator<T>.Multiply(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary multiplication (*) for the given type(s); this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static TArg1 MultiplyAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
+ {
+ return Operator<TArg2, TArg1>.Multiply(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary division (/) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static T Divide<T>(T value1, T value2)
+ {
+ return Operator<T>.Divide(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary division (/) for the given type(s); this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static TArg1 DivideAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
+ {
+ return Operator<TArg2, TArg1>.Divide(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary equality (==) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static bool Equal<T>(T value1, T value2)
+ {
+ return Operator<T>.Equal(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary inequality (!=) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static bool NotEqual<T>(T value1, T value2)
+ {
+ return Operator<T>.NotEqual(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary greater-than (>) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static bool GreaterThan<T>(T value1, T value2)
+ {
+ return Operator<T>.GreaterThan(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary less-than (<) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static bool LessThan<T>(T value1, T value2)
+ {
+ return Operator<T>.LessThan(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary greater-than-on-eqauls (>=) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static bool GreaterThanOrEqual<T>(T value1, T value2)
+ {
+ return Operator<T>.GreaterThanOrEqual(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates binary less-than-or-equal (<=) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static bool LessThanOrEqual<T>(T value1, T value2)
+ {
+ return Operator<T>.LessThanOrEqual(value1, value2);
+ }
+ /// <summary>
+ /// Evaluates integer division (/) for the given type; this will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary><remarks>
+ /// This operation is particularly useful for computing averages and
+ /// similar aggregates.
+ /// </remarks>
+ public static T DivideInt32<T>(T value, int divisor)
+ {
+ return Operator<int,T>.Divide(value, divisor);
+ }
+ public static T Max<T>(T v1, T v2)
+ {
+ return Operator.GreaterThanOrEqual (v1, v2) ? v1 : v2;
+ }
+ public static T Min<T>(T v1, T v2)
+ {
+ return Operator.LessThanOrEqual (v1, v2) ? v1 : v2;
+ }
+ }
+ /// <summary>
+ /// Provides standard operators (such as addition) that operate over operands of
+ /// different types. For operators, the return type is assumed to match the first
+ /// operand.
+ /// </summary>
+ /// <seealso cref="Operator<T>"/>
+ /// <seealso cref="Operator"/>
+ public static class Operator<TValue, TResult>
+ {
+ private static readonly Func<TValue, TResult> convert;
+ /// <summary>
+ /// Returns a delegate to convert a value between two types; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide a suitable cast, or for
+ /// Nullable<TInner> if TInner does not provide this cast.
+ /// </summary>
+ public static Func<TValue, TResult> Convert { get { return convert; } }
+ static Operator()
+ {
+ convert = ExpressionUtil.CreateExpression<TValue, TResult>(body => Expression.Convert(body, typeof(TResult)));
+ add = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Add, true);
+ subtract = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Subtract, true);
+ multiply = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Multiply, true);
+ divide = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Divide, true);
+ }
+
+ private static readonly Func<TResult, TValue, TResult> add, subtract, multiply, divide;
+ /// <summary>
+ /// Returns a delegate to evaluate binary addition (+) for the given types; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<TResult, TValue, TResult> Add { get { return add; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary subtraction (-) for the given types; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<TResult, TValue, TResult> Subtract { get { return subtract; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary multiplication (*) for the given types; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<TResult, TValue, TResult> Multiply { get { return multiply; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary division (/) for the given types; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<TResult, TValue, TResult> Divide { get { return divide; } }
+ }
+
+ /// <summary>
+ /// Provides standard operators (such as addition) over a single type
+ /// </summary>
+ /// <seealso cref="Operator"/>
+ /// <seealso cref="Operator<TValue,TResult>"/>
+ public static class Operator<T>
+ {
+ static readonly INullOp<T> nullOp;
+ internal static INullOp<T> NullOp { get { return nullOp; } }
+
+ static readonly T zero;
+ /// <summary>
+ /// Returns the zero value for value-types (even full Nullable<TInner>) - or null for reference types
+ /// </summary>
+ public static T Zero { get { return zero;} }
+
+ static readonly Func<T, T> negate, not;
+ static readonly Func<T, T, T> or, and, xor;
+ /// <summary>
+ /// Returns a delegate to evaluate unary negation (-) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T> Negate { get { return negate; } }
+ /// <summary>
+ /// Returns a delegate to evaluate bitwise not (~) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T> Not { get { return not; } }
+ /// <summary>
+ /// Returns a delegate to evaluate bitwise or (|) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, T> Or { get { return or; } }
+ /// <summary>
+ /// Returns a delegate to evaluate bitwise and (&) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, T> And { get { return and; } }
+ /// <summary>
+ /// Returns a delegate to evaluate bitwise xor (^) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, T> Xor { get { return xor; } }
+
+ static readonly Func<T, T, T> add, subtract, multiply, divide;
+ /// <summary>
+ /// Returns a delegate to evaluate binary addition (+) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, T> Add { get { return add; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary subtraction (-) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, T> Subtract { get { return subtract; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary multiplication (*) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, T> Multiply { get { return multiply; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary division (/) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, T> Divide { get { return divide; } }
+
+
+ static readonly Func<T, T, bool> equal, notEqual, greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual;
+ /// <summary>
+ /// Returns a delegate to evaluate binary equality (==) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, bool> Equal { get { return equal; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary inequality (!=) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, bool> NotEqual { get { return notEqual; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary greater-then (>) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, bool> GreaterThan { get { return greaterThan; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary less-than (<) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, bool> LessThan { get { return lessThan; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary greater-than-or-equal (>=) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, bool> GreaterThanOrEqual { get { return greaterThanOrEqual; } }
+ /// <summary>
+ /// Returns a delegate to evaluate binary less-than-or-equal (<=) for the given type; this delegate will throw
+ /// an InvalidOperationException if the type T does not provide this operator, or for
+ /// Nullable<TInner> if TInner does not provide this operator.
+ /// </summary>
+ public static Func<T, T, bool> LessThanOrEqual { get { return lessThanOrEqual; } }
+
+ static Operator()
+ {
+ add = ExpressionUtil.CreateExpression<T, T, T>(Expression.Add);
+ subtract = ExpressionUtil.CreateExpression<T, T, T>(Expression.Subtract);
+ divide = ExpressionUtil.CreateExpression<T, T, T>(Expression.Divide);
+ multiply = ExpressionUtil.CreateExpression<T, T, T>(Expression.Multiply);
+
+ greaterThan = ExpressionUtil.CreateExpression<T, T, bool>(Expression.GreaterThan);
+ greaterThanOrEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.GreaterThanOrEqual);
+ lessThan = ExpressionUtil.CreateExpression<T, T, bool>(Expression.LessThan);
+ lessThanOrEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.LessThanOrEqual);
+ equal = ExpressionUtil.CreateExpression<T, T, bool>(Expression.Equal);
+ notEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.NotEqual);
+
+ negate = ExpressionUtil.CreateExpression<T, T>(Expression.Negate);
+ and = ExpressionUtil.CreateExpression<T, T, T>(Expression.And);
+ or = ExpressionUtil.CreateExpression<T, T, T>(Expression.Or);
+ not = ExpressionUtil.CreateExpression<T, T>(Expression.Not);
+ xor = ExpressionUtil.CreateExpression<T, T, T>(Expression.ExclusiveOr);
+
+ Type typeT = typeof(T);
+ if(typeT.IsValueType && typeT.IsGenericType && (typeT.GetGenericTypeDefinition() == typeof(Nullable<>))) {
+ // get the *inner* zero (not a null Nullable<TValue>, but default(TValue))
+ Type nullType = typeT.GetGenericArguments()[0];
+ zero = (T)Activator.CreateInstance(nullType);
+ nullOp = (INullOp<T>)Activator.CreateInstance(
+ typeof(StructNullOp<>).MakeGenericType(nullType));
+ } else {
+ zero = default(T);
+ if (typeT.IsValueType)
+ {
+ nullOp = (INullOp<T>)Activator.CreateInstance(
+ typeof(StructNullOp<>).MakeGenericType(typeT));
+ }
+ else
+ {
+ nullOp = (INullOp<T>)Activator.CreateInstance(
+ typeof(ClassNullOp<>).MakeGenericType(typeT));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using Crow;
+using Glfw;
+using Samples;
+
+namespace HelloWorld
+{
+ class Program : Interface {
+ Program() : base (800, 600, true) {}
+ static void Main (string[] args) {
+ //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 (@"<Window Caption='hello world'/>");
+ app.Run ();
+ }
+ }
+ protected override void OnInitialized()
+ {
+ Load ("/mnt/devel/crow/Samples/AnimTest/ui/anim.crow");
+ }
+
+ public override void UpdateFrame()
+ {
+ base.UpdateFrame();
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0"?>
+<Container Margin="10" Width="500" Background="/mnt/devel/crow/Samples/AnimTest/ui/background.jpg">
+<!-- <Image Path="/mnt/devel/crow/Samples/AnimTest/ui/background.jpg" SvgSub="True" Height="200"/>-->
+ <HorizontalStack Height="Fit" Width="Fit" Spacing="10" VerticalAlignment="Bottom" >
+ <Label Background="Teal" Width="30%" Margin="10" CornerRadius="10" Font="bold, 14" TextAlignment="Center"/>
+ <Label Background="Teal" Width="30%" Margin="10" CornerRadius="10" Font="bold, 14" TextAlignment="Center"/>
+ <Label Background="Teal" Width="30%" Margin="10" CornerRadius="10" Font="bold, 14" TextAlignment="Center"/>
+ </HorizontalStack>
+</Container>
+
--- /dev/null
+<?xml version="1.0"?>
+<Widget Height="400" Width="260" Background="/mnt/devel/crow/Samples/AnimTest/ui/background.jpg"/>
+<!--<Widget Height="100" Width="100" Background="#Crow.Icons.checkbox.svg"/>-->
+
static void Main ()
{
using (BasicTests app = new BasicTests ()) {
- app.SolidBackground = false;
+ //app.SolidBackground = false;
app.Run ();
}
}
protected override void OnInitialized ()
{
- Commands = new CommandGroup (
+ /*Commands = new CommandGroup (
new Crow.Command("command1", new Action(() => Console.WriteLine ("command1 triggered"))),
new Crow.Command("command2", new Action(() => Console.WriteLine ("command2 triggered"))),
new Crow.Command("command3", new Action(() => Console.WriteLine ("command3 triggered"))),
new Crow.Command("command4", new Action(() => Console.WriteLine ("command4 triggered")))
- );
+ );*/
// += KeyboardKeyDown1;
int idx = 0;
string [] testFiles;
-
-
- public override bool OnKeyDown (Key key)
+ public override bool OnKeyDown (KeyEventArgs e)
{
try {
- switch (key) {
+ switch (e.Key) {
case Key.Escape:
Quit ();
break;
NotifyValueChanged ("TestList", TestList);
break;
default:
- return base.OnKeyDown (key);
+ return base.OnKeyDown (e);
}
ClearInterface ();
class Program : Interface {
Program() : base (800, 600, true) {}
static void Main (string[] args) {
+ //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 (@"<Window Caption='hello world'/>");
<?xml version="1.0"?>
-<Label Text="Hello World"/>
+
+ <!--<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/>-->
using System.Collections.Generic;
using Encoding = System.Text.Encoding;
using Samples;
+using System.Threading;
namespace ShowCase
{
};
static void Main ()
{
+ //Interface.PreferedBackendType = Drawing2D.BackendType.Egl;
+
initDebugLog ();
Environment.SetEnvironmentVariable ("FONTCONFIG_PATH", @"C:\Users\Jean-Philippe\source\vcpkg\installed\x64-windows\tools\fontconfig\fonts");
app.Run ();
}
}
+ public override void Run () {
+ initBackend ();
+
+ if (!SingleThreaded) {
+ Thread t = new Thread (InterfaceThread) {
+ IsBackground = true
+ };
+ t.Start ();
+ }
+
+ Init ();
+
+ if (SingleThreaded) {
+ while (!Glfw3.WindowShouldClose (WindowHandle)) {
+ Glfw3.PollEvents ();
+ try {
+ Update();
+ UpdateFrame ();
+ } catch (Exception ex) {
+ showError (ex);
+ crowContainer.SetChild (null);
+ }
+ Thread.Sleep (UPDATE_INTERVAL);
+ }
+ } else {
+ while (!Glfw3.WindowShouldClose (hWin)) {
+ Glfw3.PollEvents ();
+ UpdateFrame ();
+ Thread.Sleep (POLLING_INTERVAL);
+ }
+ }
+
+ Terminate ();
+ }
public Container crowContainer;
Stopwatch reloadChrono = new Stopwatch ();
<Container Name="CrowContainer" Height="60%" Background="Black"/>
<Splitter/>
<VerticalStack CacheEnabled="true">
- <Menu Data="{EditorAllCommands}" Height="Fit" Width="Stretched">
+ <!--<Menu Data="{EditorAllCommands}" Height="Fit" Width="Stretched">
<ItemTemplate DataType="Crow.Command" Path="Interfaces/menuCommand.itmp"/>
<ItemTemplate DataType="Crow.CommandGroup" >
<MenuItem Data="{Commands}" Width="Fit" IsEnabled="{CanExecute}"
ItemTemplate="Interfaces/menuItem.itmp">
</MenuItem>
</ItemTemplate>
- </Menu>
- <!-- <Wrapper Orientation="Vertical" Height="Fit">
+ </Menu>-->
+ <Wrapper Orientation="Vertical" Height="Fit">
<Button Style="IcoButton" Command="{CMDNew}" />
<Button Style="IcoButton" Command="{CMDSave}" />
<Button Style="IcoButton" Command="{CMDSaveAs}" />
Tooltip="Add '*source* where you want to load the source in the editor."/>
</VerticalStack>
</Popper>
- </Wrapper>-->
+ </Wrapper>
<HorizontalStack>
<Editor Name="tb" Text="{Source}" Multiline="true" Font="consolas, 12" Focusable="true" Height="Stretched" Width="Stretched"
TextChanged="onTextChanged" KeyDown="textView_KeyDown" ContextCommands="{EditorEditCommands}"
- SelectionChanged="onEditorSelectionChanged"
+ SelectionChanged="onEditorSelectionChanged" ClipToClientRect="true"
Foreground="DarkGrey" Background="White" MouseWheelSpeed="20"/>
<ScrollBar Value="{²../tb.ScrollY}"
LargeIncrement="{../tb.PageHeight}" SmallIncrement="1"
--- /dev/null
+<?xml version="1.0"?>
+<Image Path="/usr/share/icons/breeze/categories/32/applications-education.svg"/>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<VerticalStack Margin="10" Background="Grey">
+ <Button
+ Foreground="LightGrey"
+ MouseEnter="{Foreground=White}"
+ MouseLeave="{Foreground=LightGrey}"
+ Background="vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet"
+ MouseUp="{Background=vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet}"
+ MouseDown="{Background=vgradient|0:Jet|0.1:Grey|0.9:Grey|1:LightGrey}">
+ <Template>
+ <Border Foreground="Black" CornerRadius="10" Background="{./Background}" Margin="7">
+ <Label Foreground="{./Foreground}" Text="{./Caption}"/>
+ </Border>
+ </Template>
+ </Button >
+ <CheckBox Width="200"
+ Foreground="Black"
+ Background="vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet"
+ Unchecked="{Background=vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet};{Foreground=Black}"
+ Checked="{Background=vgradient|0:Jet|0.1:Grey|0.9:Grey|1:LightGrey};{Foreground=DodgerBlue}">
+ <Template>
+ <Border Foreground="{./Foreground}" CornerRadius="10" Background="{./Background}" Margin="7">
+ <Label Text="{./Caption}"/>
+ </Border>
+ </Template>
+ </CheckBox >
+ <HorizontalStack Height="Fit" Width="Fit">
+ <RadioButton Width="200"
+ Foreground="Black"
+ Background="vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet"
+ Unchecked="{Background=vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet};{Foreground=Black}"
+ Checked="{Background=vgradient|0:Jet|0.1:Grey|0.9:Grey|1:LightGrey};{Foreground=DodgerBlue}">
+ <Template>
+ <Border Foreground="{./Foreground}" CornerRadius="10" Background="{./Background}" Margin="7">
+ <Label Text="{./Caption}"/>
+ </Border>
+ </Template>
+ </RadioButton >
+ <RadioButton Width="200"
+ Foreground="Black"
+ Background="vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet"
+ Unchecked="{Background=vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet};{Foreground=Black}"
+ Checked="{Background=vgradient|0:Jet|0.1:Grey|0.9:Grey|1:LightGrey};{Foreground=DodgerBlue}">
+ <Template>
+ <Border Foreground="{./Foreground}" CornerRadius="10" Background="{./Background}" Margin="7">
+ <Label Text="{./Caption}"/>
+ </Border>
+ </Template>
+ </RadioButton >
+ <RadioButton Width="200"
+ Foreground="Black"
+ Background="vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet"
+ Unchecked="{Background=vgradient|0:LightGrey|0.1:Grey|0.9:Grey|1:Jet};{Foreground=Black}"
+ Checked="{Background=vgradient|0:Jet|0.1:Grey|0.9:Grey|1:LightGrey};{Foreground=DodgerBlue}">
+ <Template>
+ <Border Foreground="{./Foreground}" CornerRadius="10" Background="{./Background}" Margin="7">
+ <Label Text="{./Caption}"/>
+ </Border>
+ </Template>
+ </RadioButton >
+ </HorizontalStack>
+</VerticalStack>
\ No newline at end of file