Added Rectangle to the shapes.

Added a shortcurt "Ctrl+Shift+Space" to open menu.
This commit is contained in:
Creeper Lv
2025-12-30 00:51:01 +11:00
parent 25efa1127f
commit 2eb59564b4
12 changed files with 275 additions and 111 deletions

View File

@@ -1,7 +1,87 @@
namespace Progrart.Core.Graphics
using Jint;
using Jint.Native;
using Progrart.Core.JSExecution;
using SkiaSharp;
using System.Diagnostics;
namespace Progrart.Core.Graphics
{
public class Rectangle : BaseElement
{
float StrokeWidth;
SKPoint Start;
SKPoint Size;
SKColorF Color;
SKShader? shader = null;
public override void SetupProperties(Engine engine)
{
base.SetupProperties(engine);
if (__object != null)
{
{
JsObject point = new JsObject(engine);
point.Set("x", 0);
point.Set("y", 0);
__object.Set("Position", point);
}
__object.Set("StrokeWidth", 1);
__object.Set("Color", ProgrartFunctions.color(engine, 1, 1, 1, 1));
{
JsObject point = new JsObject(engine);
point.Set("x", 0);
point.Set("y", 0);
__object.Set("Size", point);
}
}
}
public override void LoadProperties()
{
if (__object is not null)
{
StrokeWidth = (float)__object.Get("StrokeWidth").AsNumber();
{
if (__object.Get("Position") is JsObject Start)
{
this.Start = ProgrartConversion.ObtainSKPointFromJsObject(Start);
}
}
{
if (__object.Get("Size") is JsObject End)
{
this.Size = ProgrartConversion.ObtainSKPointFromJsObject(End);
}
}
{
if (__object.Get("Color") is JsObject Color)
{
this.Color = ProgrartConversion.ObtainSKColorFFromJsObject(Color);
}
}
if (__object.Get("Shader") is JsObject shaderObj)
shader = ProgrartConversion.ObtainFromJsObject(shaderObj);
}
}
public override void Render(RenderContext context)
{
base.Render(context);
LoadProperties();
SKPoint FinalStartPos = context.TranslatePoint(Start);
SKPoint FinalEndPos = context.TranslatePoint(Size);
Trace.WriteLine($"Draw Rectangle from {FinalStartPos} to {FinalEndPos} using {Color} with size of {StrokeWidth}.");
context.DrawingCore.canvas.DrawRect(
FinalStartPos.X, FinalStartPos.Y,
FinalEndPos.X, FinalEndPos.Y,
new SKPaint()
{
ColorF = Color,
StrokeWidth = StrokeWidth,
Shader = shader
}
);
}
}
}

View File

@@ -32,7 +32,6 @@ namespace Progrart.Core.JSExecution
public void Dispose()
{
Engine.Dispose();
}
}
}

View File

@@ -19,7 +19,6 @@ namespace Progrart.Core.JSExecution
}
public void SetupCalls()
{
engine.Engine.SetValue("visual_root", visual_root);
Jint.Native.Json.JsonSerializer serializer = new Jint.Native.Json.JsonSerializer(engine.Engine);
engine.Engine.SetValue("log", new Action<JsValue>((v) =>
{
@@ -30,7 +29,9 @@ namespace Progrart.Core.JSExecution
else
Trace.WriteLine(v);
}));
engine.Engine.SetValue("visual_root", visual_root);
engine.Engine.SetValue("line", line);
engine.Engine.SetValue("rectangle", rectangle);
engine.Engine.SetValue("color4", color4);
engine.Engine.SetValue("color3", color3);
engine.Engine.SetValue("linear_gradient", linear_gradient);
@@ -59,7 +60,13 @@ namespace Progrart.Core.JSExecution
}
public JsObject line()
{
return ProgrartFunctions.CreateLine(this);
//return ProgrartFunctions.CreateLine(this);
return ProgrartFunctions.CreateElement<Line>(this);
}
public JsObject rectangle()
{
//return ProgrartFunctions.CreateLine(this);
return ProgrartFunctions.CreateElement<Rectangle>(this);
}
public RenderContext RenderImage(int Scale, string script, ExecuteArguments arguments)
{

View File

@@ -118,5 +118,13 @@ namespace Progrart.Core.JSExecution
element.SetupProperties(executor.engine.Engine);
return obj;
}
public static JsObject CreateElement<T>(ProgrartExecutor executor) where T: BaseElement
{
T element=Activator.CreateInstance<T>() as T;
var obj = WrapObject(executor, executor.RegisterObject(element));
element.__object = obj;
element.SetupProperties(executor.engine.Engine);
return obj;
}
}
}

View File

@@ -291,8 +291,19 @@
<Style Selector="ContextMenu">
<Setter Property="FontFamily" Value="{StaticResource SarasaMonoSlabCLFont}"/>
</Style>
<Style Selector="MenuItem:selected">
<Style Selector="^ /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackground}" />
</Style>
</Style>
<Style Selector="MenuItem:pressed /template/ Border#PART_LayoutRoot:pointerover">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPressed}" />
</Style>
<Style Selector="MenuItem">
<Setter Property="FontFamily" Value="{StaticResource SarasaMonoSlabCLFont}"/>
<Setter Property="Padding" Value="16,2"/>
<Setter Property="FontSize" Value="12"/>
</Style>
</Application.Styles>
</Application>

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
namespace Progrart.Commands
{
public class GenericCommand : ICommand
{
public event EventHandler? CanExecuteChanged;
public Func<object?, bool>? Checker = null;
public Action<object?>? onExecute = null;
public bool CanExecute(object? parameter)
{
return Checker?.Invoke(parameter) ?? true;
}
public void Execute(object? parameter)
{
onExecute?.Invoke(parameter);
}
}
}

View File

@@ -5,14 +5,14 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Progrart.Controls.BaseEditor">
<avaloniaedit:TextEditor Name="CodeEditBox" Text="" SyntaxHighlighting="JavaScript"
<avaloniaedit:TextEditor Name="CodeEditBox" Text=""
ShowLineNumbers="True"
FontFamily="Sarasa Mono Slab CL,Cascadia Code,Consolas,Menlo,Monospace">
<avaloniaedit:TextEditor.ContextMenu>
<ContextMenu>
<MenuItem Name="Copy" Click="Copy_Click"/>
<MenuItem Name="Cut" Click="Cut_Click"/>
<MenuItem Name="Paste" Click="Paste_Click"/>
<MenuItem Header="_Copy" Click="Copy_Click"/>
<MenuItem Header="Cut (_X)" Click="Cut_Click"/>
<MenuItem Header="Paste (_V)" Click="Paste_Click"/>
</ContextMenu>
</avaloniaedit:TextEditor.ContextMenu>
</avaloniaedit:TextEditor>

View File

@@ -4,6 +4,7 @@ using Avalonia.Input;
using Avalonia.Markup.Xaml;
using AvaloniaEdit;
using AvaloniaEdit.TextMate;
using Progrart.Commands;
using System;
using System.Windows.Input;
using TextMateSharp.Grammars;
@@ -12,8 +13,8 @@ namespace Progrart.Controls;
public partial class BaseEditor : UserControl
{
RegistryOptions _registryOptions;
TextMate.Installation _textMateInstallation;
RegistryOptions? _registryOptions;
TextMate.Installation? _textMateInstallation;
public string Text
{
get => CodeEditBox.Text;
@@ -23,6 +24,8 @@ public partial class BaseEditor : UserControl
public BaseEditor()
{
InitializeComponent();
if (!OperatingSystem.IsBrowser())
{
var _textEditor = CodeEditBox;
_registryOptions = new RegistryOptions(ThemeName.DarkPlus);
@@ -32,7 +35,7 @@ public partial class BaseEditor : UserControl
var saveBinding = new KeyBinding
{
Gesture = new KeyGesture(Key.S, KeyModifiers.Control),
Command = new saveCmd() { onSave = Save }
Command = new GenericCommand() { onExecute = (_) => Save() }
};
CodeEditBox.KeyBindings.Add(saveBinding);
@@ -41,24 +44,14 @@ public partial class BaseEditor : UserControl
{
onSaveCmd?.Invoke();
}
class saveCmd : ICommand
{
public event EventHandler? CanExecuteChanged;
public Action? onSave;
public bool CanExecute(object? parameter)
{
return true;
}
public void Execute(object? parameter)
{
onSave?.Invoke();
}
}
public void SetGrammerByExtension(string extension_name)
{
_textMateInstallation.SetGrammar(
_registryOptions.GetScopeByLanguageId(
if (OperatingSystem.IsBrowser())
{
return;
}
_textMateInstallation?.SetGrammar(
_registryOptions?.GetScopeByLanguageId(
_registryOptions.GetLanguageByExtension(extension_name).Id
)
);

View File

@@ -8,6 +8,7 @@ using Progrart.Controls.TabSystem;
using Progrart.Core;
using Progrart.Core.JSExecution;
using Progrart.Pages;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
@@ -75,7 +76,7 @@ public partial class ProgrartEditorPage : UserControl, ITabPage, IEditorPage
public bool IsSameFile(IStorageFile file)
{
return (this.file?.Path==file.Path);
return (this.file?.Path == file.Path);
}
public void LoadDocument(IStorageFile file)
@@ -95,6 +96,12 @@ public partial class ProgrartEditorPage : UserControl, ITabPage, IEditorPage
using var stream = await file.OpenReadAsync();
using StreamReader sr = new StreamReader(stream);
var text = sr.ReadToEnd();
if (OperatingSystem.IsBrowser())
{
CodeEditor.Text = text;
}
else
Dispatcher.UIThread.Invoke(() =>
{
CodeEditor.Text = text;

View File

@@ -33,7 +33,7 @@
<Border Effect="blur(25)">
<TextBlock Margin="8,2" HorizontalAlignment="Center">Progart</TextBlock>
</Border>
<Button Padding="16,1" BorderThickness="1,1,1,0" Margin="-1,-1,-1,0" CornerRadius="14">
<Button Padding="16,1" BorderThickness="1,1,1,0" Margin="-1,-1,-1,0" CornerRadius="14" Name="MenuButton">
<Button.Flyout>
<MenuFlyout>
<MenuItem Header="_File">

View File

@@ -1,6 +1,8 @@
using Acornima.Ast;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using Progrart.Commands;
using Progrart.Controls;
using Progrart.Core;
using Progrart.Core.JSExecution;
@@ -19,6 +21,35 @@ public partial class MainView : UserControl
InitializeComponent();
Trace.Listeners.Add(new ConsoleLogger());
EditorProvider.setHost(MainTabHost);
this.KeyBindings.Add(new Avalonia.Input.KeyBinding()
{
Gesture = new Avalonia.Input.KeyGesture(Avalonia.Input.Key.Space,
Avalonia.Input.KeyModifiers.Shift | Avalonia.Input.KeyModifiers.Control),
Command = new GenericCommand()
{
Checker = (_) => true,
onExecute = (_) =>
{
MenuButton.ContextMenu?.Open();
}
}
});
this.KeyBindings.Add(new Avalonia.Input.KeyBinding()
{
Gesture = new Avalonia.Input.KeyGesture(Avalonia.Input.Key.F5,
Avalonia.Input.KeyModifiers.None),
Command = new GenericCommand()
{
Checker = (_) => true,
onExecute = (_) =>
{
Execute();
}
}
});
ToolTip.SetTip(MenuButton, "Press Shift+Ctrl+Space to open menu");
ToolTip.SetIsOpen(MenuButton, true);
BottomPanelToggle.IsCheckedChanged += (a, b) =>
{
bool v = BottomPanelToggle.IsChecked == true;
@@ -77,6 +108,12 @@ public partial class MainView : UserControl
};
LeftPanelToggle.IsChecked = true;
RunButton.Click += (_, _) =>
{
Execute();
};
}
private void Execute()
{
if (MainTabHost.GetCurrentPage() is IEditorPage editor)
{
@@ -85,7 +122,6 @@ public partial class MainView : UserControl
args.data["Debug"] = $"{IsDebugBox.IsChecked ?? false}".ToLower();
editor.Execute(args);
}
};
}
private void OutputClear_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)