Added DialogHost as dialog system.

Implemented create folder and progrart image in menu in file explorer.
This commit is contained in:
Creeper Lv
2025-12-24 00:55:56 +11:00
parent b47fe42a0b
commit 75b9292c34
18 changed files with 728 additions and 203 deletions

View File

@@ -6,17 +6,19 @@
<ItemGroup> <ItemGroup>
<!-- Avalonia packages --> <!-- Avalonia packages -->
<!-- Important: keep version in sync! --> <!-- Important: keep version in sync! -->
<PackageVersion Include="Avalonia" Version="11.3.9" /> <PackageVersion Include="Avalonia" Version="11.3.10" />
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.3.0" /> <PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.3.0" />
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.9" /> <PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.10" />
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.9" /> <PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.10" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.9" /> <PackageVersion Include="Avalonia.Diagnostics" Version="11.3.10" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.9" /> <PackageVersion Include="Avalonia.Desktop" Version="11.3.10" />
<PackageVersion Include="Avalonia.iOS" Version="11.3.9" /> <PackageVersion Include="Avalonia.iOS" Version="11.3.10" />
<PackageVersion Include="Avalonia.Browser" Version="11.3.9" /> <PackageVersion Include="Avalonia.Browser" Version="11.3.10" />
<PackageVersion Include="Avalonia.Android" Version="11.3.9" /> <PackageVersion Include="Avalonia.Android" Version="11.3.10" />
<!--<PackageVersion Include="Devolutions.AvaloniaTheme.DevExpress" Version="2025.12.4" /> <!--<PackageVersion Include="Devolutions.AvaloniaTheme.DevExpress" Version="2025.12.4" />
<PackageVersion Include="Devolutions.AvaloniaTheme.MacOS" Version="2025.12.4" />--> <PackageVersion Include="Devolutions.AvaloniaTheme.MacOS" Version="2025.12.4" />-->
<PackageVersion Include="AvaloniaEdit.TextMate" Version="11.3.0" />
<PackageVersion Include="DialogHost.Avalonia" Version="0.10.3" />
<PackageVersion Include="Jint" Version="4.4.2" /> <PackageVersion Include="Jint" Version="4.4.2" />
<PackageVersion Include="Microsoft.Maui.Graphics" Version="10.0.11" /> <PackageVersion Include="Microsoft.Maui.Graphics" Version="10.0.11" />
<PackageVersion Include="Microsoft.Maui.Graphics.Skia" Version="10.0.11" /> <PackageVersion Include="Microsoft.Maui.Graphics.Skia" Version="10.0.11" />

View File

@@ -7,11 +7,18 @@ namespace Progrart.Core.ProjectSystem
[Serializable] [Serializable]
public class Project public class Project
{ {
public List<BuildConfiguration> Configurations = new List<BuildConfiguration>();
} }
[Serializable] [Serializable]
public class BuildConfiguration public class BuildConfiguration
{ {
public string? Name; public string? Name;
public List<BuildItem> Items = new List<BuildItem>();
}
[Serializable]
public class BuildItem
{
public string? Source;
public string? Target;
} }
} }

View File

@@ -1,14 +1,158 @@
<Application xmlns="https://github.com/avaloniaui" <Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dialoghostavalonia="using:DialogHostAvalonia"
xmlns:local="using:Progrart" xmlns:local="using:Progrart"
x:Class="Progrart.App" x:Class="Progrart.App"
RequestedThemeVariant="Default"> RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. --> <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.Resources>
<ResourceDictionary>
<ControlTheme x:Key="{x:Type RadioButton}" TargetType="RadioButton">
<Setter Property="Background" Value="{DynamicResource RadioButtonBackground}" />
<Setter Property="Foreground" Value="{DynamicResource RadioButtonForeground}" />
<Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrush}" />
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
<Setter Property="Padding" Value="8,2" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<ControlTemplate TargetType="RadioButton">
<Border
Name="RootBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid ColumnDefinitions="*">
<Grid Height="{DynamicResource RadioButtonMinHeight}" VerticalAlignment="Top">
<Border
Name="OuterBorder"
UseLayoutRounding="False" />
<Border
Name="CheckOuterBorder"
Opacity="0"
UseLayoutRounding="False" />
<Border
CornerRadius="12"
Name="CheckGlyph"
Background="#2288EE"
Opacity="0"
/>
</Grid>
<ContentPresenter
Name="PART_ContentPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Foreground="{TemplateBinding Foreground}" />
</Grid>
</Border>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<!-- PointerOver State -->
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource RadioButtonForegroundPointerOver}" />
</Style>
<Style Selector="^:pointerover /template/ Border#RootBorder">
<Setter Property="Background" Value="{DynamicResource RadioButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrushPointerOver}" />
</Style>
<Style Selector="^:pointerover /template/ Border#OuterBorder">
</Style>
<Style Selector="^:pointerover /template/ Border#CheckOuterBorder">
<!-- <Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterBorderCheckedStrokePointerOver}" />
<Setter Property="Fill" Value="{DynamicResource RadioButtonOuterBorderCheckedFillPointerOver}" />-->
</Style>
<Style Selector="^:pointerover /template/ Border#CheckGlyph">
<Setter Property="Background" Value="#3090FF" />
</Style>
<!-- Pressed State -->
<Style Selector="^:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource RadioButtonForegroundPressed}" />
</Style>
<Style Selector="^:pressed /template/ Border#RootBorder">
<Setter Property="Background" Value="{DynamicResource RadioButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrushPressed}" />
</Style>
<Style Selector="^:pressed /template/ Border#OuterBorder">
<!-- <Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterBorderStrokePressed}" />
<Setter Property="Fill" Value="{DynamicResource RadioButtonOuterBorderFillPressed}" />-->
</Style>
<Style Selector="^:pressed /template/ Border#CheckOuterBorder">
<!--<Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterBorderCheckedStrokePressed}" />
<Setter Property="Fill" Value="{DynamicResource RadioButtonOuterBorderCheckedFillPressed}" />-->
</Style>
<Style Selector="^:pressed /template/ Border#CheckGlyph">
<Setter Property="Background" Value="#1070D0" />
</Style>
<!-- Disabled State -->
<Style Selector="^:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource RadioButtonForegroundDisabled}" />
</Style>
<Style Selector="^:disabled /template/ Border#RootBorder">
<Setter Property="Background" Value="{DynamicResource RadioButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrushDisabled}" />
</Style>
<Style Selector="^:disabled /template/ Border#OuterBorder">
</Style>
<Style Selector="^:disabled /template/ Border#CheckOuterBorder">
</Style>
<Style Selector="^:disabled /template/ Border#CheckGlyph">
<Setter Property="Background" Value="#2050A0" />
</Style>
<!-- Checked State -->
<Style Selector="^:checked /template/ Border#CheckGlyph">
<Setter Property="Opacity" Value="1" />
</Style>
<Style Selector="^:checked /template/ Border#OuterBorder">
<Setter Property="Opacity" Value="0" />
</Style>
<Style Selector="^:checked /template/ Border#CheckOuterBorder">
<Setter Property="Opacity" Value="1" />
</Style>
</ControlTheme>
</ResourceDictionary>
</Application.Resources>
<Application.Styles> <Application.Styles>
<FluentTheme/> <FluentTheme/>
<!--<DevolutionsDevExpressTheme />--> <!--<DevolutionsDevExpressTheme />-->
<!--<DevolutionsMacOsTheme/>--> <!--<DevolutionsMacOsTheme/>-->
<StyleInclude Source="avares://AvaloniaEdit/Themes/Fluent/AvaloniaEdit.xaml" /> <StyleInclude Source="avares://AvaloniaEdit/Themes/Fluent/AvaloniaEdit.xaml" />
<dialoghostavalonia:DialogHostStyles/>
</Application.Styles> </Application.Styles>
</Application> </Application>

View File

@@ -23,6 +23,7 @@ public partial class App : Application
IconProvider.Register(new DefaultIconProvider()); IconProvider.Register(new DefaultIconProvider());
EditorProvider.Register("text", "Default Text Editor", typeof(EditorPage)); EditorProvider.Register("text", "Default Text Editor", typeof(EditorPage));
EditorProvider.Register("image", "Default Image Viewer", typeof(ImageViewPage)); EditorProvider.Register("image", "Default Image Viewer", typeof(ImageViewPage));
EditorProvider.Register("progrart", "Default Progrart Editor", typeof(ProgrartEditorPage));
EditorProvider.BindFileType("cs", "text"); EditorProvider.BindFileType("cs", "text");
EditorProvider.BindFileType("c", "text"); EditorProvider.BindFileType("c", "text");
EditorProvider.BindFileType("cpp", "text"); EditorProvider.BindFileType("cpp", "text");
@@ -33,7 +34,7 @@ public partial class App : Application
EditorProvider.BindFileType("cpp", "text"); EditorProvider.BindFileType("cpp", "text");
EditorProvider.BindFileType("json", "text"); EditorProvider.BindFileType("json", "text");
EditorProvider.BindFileType("sh", "text"); EditorProvider.BindFileType("sh", "text");
EditorProvider.BindFileType("progrart", "text"); EditorProvider.BindFileType("progrart", "progrart");
EditorProvider.BindFileType("bashrc", "text"); EditorProvider.BindFileType("bashrc", "text");
EditorProvider.BindFileType("png", "image"); EditorProvider.BindFileType("png", "image");
EditorProvider.BindFileType("bmp", "image"); EditorProvider.BindFileType("bmp", "image");

View File

@@ -0,0 +1,11 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:avaloniaedit="https://github.com/avaloniaui/avaloniaedit"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
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"
ShowLineNumbers="True"
FontFamily="Sarasa Mono Slab CL,Cascadia Code,Consolas,Menlo,Monospace"/>
</UserControl>

View File

@@ -0,0 +1,37 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using AvaloniaEdit.TextMate;
using TextMateSharp.Grammars;
namespace Progrart.Controls;
public partial class BaseEditor : UserControl
{
RegistryOptions _registryOptions;
TextMate.Installation _textMateInstallation;
public string Text
{
get => CodeEditBox.Text;
set => CodeEditBox.Text = value;
}
public BaseEditor()
{
InitializeComponent();
{
var _textEditor = CodeEditBox;
_registryOptions = new RegistryOptions(ThemeName.DarkPlus);
_textMateInstallation = _textEditor.InstallTextMate(_registryOptions);
_textMateInstallation.SetGrammar(_registryOptions.GetScopeByLanguageId(_registryOptions.GetLanguageByExtension(".js").Id));
}
}
public void SetGrammerByExtension(string extension_name)
{
_textMateInstallation.SetGrammar(
_registryOptions.GetScopeByLanguageId(
_registryOptions.GetLanguageByExtension(extension_name).Id
)
);
}
}

View File

@@ -11,6 +11,15 @@
<Button.ContextMenu> <Button.ContextMenu>
<ContextMenu> <ContextMenu>
<MenuItem Header="_Open" Name="OpenFileMenuItem"/> <MenuItem Header="_Open" Name="OpenFileMenuItem"/>
<MenuItem Header="_New" Name="NewFiles">
<MenuItem Header="_Progrart Image" Name="CreateProgrartItem"/>
<MenuItem Header="_Folder" Name="CreateFolderItem"/>
</MenuItem>
<Separator/>
<MenuItem Header="_Copy"/>
<MenuItem Header="Cut (_x)"/>
<MenuItem Header="_Paste"/>
<Separator/>
<MenuItem Header="_Delete"/> <MenuItem Header="_Delete"/>
</ContextMenu> </ContextMenu>
</Button.ContextMenu> </Button.ContextMenu>

View File

@@ -2,7 +2,10 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading;
using DialogHostAvalonia;
using Progrart.Controls.TabSystem; using Progrart.Controls.TabSystem;
using Progrart.Dialogs;
using Progrart.Icons; using Progrart.Icons;
using Progrart.Pages; using Progrart.Pages;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -26,6 +29,7 @@ public partial class FileItem : UserControl
} }
else if (storageItem is IStorageFile file) else if (storageItem is IStorageFile file)
{ {
NewFiles.IsVisible = false;
FolderIcon.IsVisible = false; FolderIcon.IsVisible = false;
GenericFileIcon.IsVisible = true; GenericFileIcon.IsVisible = true;
IconContainer.Children.Clear(); IconContainer.Children.Clear();
@@ -44,14 +48,86 @@ public partial class FileItem : UserControl
NameBlock.Text = storageItem.Name; NameBlock.Text = storageItem.Name;
MainButton.DoubleTapped += async (_, _) => MainButton.DoubleTapped += async (_, _) =>
{ {
await OpenItem(); OpenItem();
}; };
OpenFileMenuItem.Click += async (a, b) => OpenFileMenuItem.Click += async (a, b) =>
{ {
await OpenItem(); OpenItem();
};
CreateFolderItem.Click += async (a, b) =>
{
InputDialog content = new();
content.SetDialogContent("Create New Folder", "Specify a name that is legal for your filesystem.");
content.onOK = async (v) =>
{
if (currentItem is IStorageFolder folder)
{
try
{
var fldr = await folder.CreateFolderAsync(v);
if (fldr is not null)
{
if (isOpen)
Dispatcher.UIThread.Invoke(() =>
{
var fitem = new FileItem(fldr);
ItemContainer.Children.Add(fitem);
});
}
else
{
content.SetErrorMessage($"{v} is not a valid name for target filesystem.");
return true;
}
}
catch (System.Exception e)
{
content.SetErrorMessage($"{v} is not a valid name for target filesystem.\nMsg:{e.Message}");
return true;
}
}
return false;
};
await DialogHost.Show(content);
};
CreateProgrartItem.Click += async (a, b) =>
{
InputDialog content = new();
content.SetDialogContent("Create A PROGRART Image", "Specify a name that is legal for your filesystem.");
content.onOK = async (v) =>
{
if (currentItem is IStorageFolder folder)
{
try
{
var fldr = await folder.CreateFileAsync($"{v}.progrart");
if (fldr is not null)
{
if (isOpen)
Dispatcher.UIThread.Invoke(() =>
{
var fitem = new FileItem(fldr);
ItemContainer.Children.Add(fitem);
});
}
else
{
content.SetErrorMessage($"{v} is not a valid name for target filesystem.");
return true;
}
}
catch (System.Exception e)
{
content.SetErrorMessage($"{v} is not a valid name for target filesystem.\nMsg:{e.Message}");
return true;
}
}
return false;
};
await DialogHost.Show(content);
}; };
} }
async Task OpenItem() void OpenItem()
{ {
if (currentItem is IStorageFolder folder) if (currentItem is IStorageFolder folder)
@@ -64,7 +140,10 @@ public partial class FileItem : UserControl
else else
{ {
isOpen = true; isOpen = true;
await LoadAll(folder); Task.Run(async () =>
{
await LoadAll(folder);
});
} }
} }
else else
@@ -88,7 +167,11 @@ public partial class FileItem : UserControl
{ {
await foreach (var item in folder.GetItemsAsync()) await foreach (var item in folder.GetItemsAsync())
{ {
ItemContainer.Children.Add(new FileItem(item)); Dispatcher.UIThread.Invoke(() =>
{
var fitem = new FileItem(item);
ItemContainer.Children.Add(fitem);
});
} }
} }
void RemoveAll() void RemoveAll()

View File

@@ -10,7 +10,9 @@
<ColumnDefinition/> <ColumnDefinition/>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="2" Background="#8888" CornerRadius="12" Name="HintBackground" IsVisible="False"/> <Border Grid.ColumnSpan="2" Background="#4888" CornerRadius="12" Name="HintBackground" IsVisible="False">
<Border BorderThickness="1,1,1,0" CornerRadius="12" BorderBrush="#8888"></Border>
</Border>
<Button Name="MainButton" MinWidth="50" Padding="6,2" VerticalAlignment="Stretch">Blank Page</Button> <Button Name="MainButton" MinWidth="50" Padding="6,2" VerticalAlignment="Stretch">Blank Page</Button>
<Button Name="CloseButton" VerticalAlignment="Stretch" Grid.Column="1" Padding="6,2"> <Button Name="CloseButton" VerticalAlignment="Stretch" Grid.Column="1" Padding="6,2">
<Viewbox Height="10" Width="10"> <Viewbox Height="10" Width="10">

View File

@@ -0,0 +1,21 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Progrart.Dialogs.InputDialog">
<StackPanel>
<TextBlock FontSize="18" Name="TitleBlock" TextWrapping="Wrap"/>
<TextBlock Name="MessageBlock" TextWrapping="Wrap"/>
<TextBox Name="InputBox" TextWrapping="Wrap" Padding="4,2" MinHeight="0"/>
<TextBlock IsVisible="False" Foreground="#FF0000" Name="ErrorBlock" TextWrapping="Wrap"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Classes="accent" Name="OKBtn" Content="OK"/>
<Button HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Name="CancelBtn" Grid.Column="1" Content="Cancel"/>
</Grid>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,74 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using DialogHostAvalonia;
using System;
using System.Threading.Tasks;
namespace Progrart.Dialogs;
public partial class InputDialog : UserControl
{
public Func<string, Task<bool>>? onOK = null;
public Func<bool>? onCancel = null;
public InputDialog()
{
InitializeComponent();
OKBtn.Click += OKBtn_Click;
CancelBtn.Click += CancelBtn_Click;
InputBox.AddHandler(KeyDownEvent, async (sender, e) =>
{
switch (e.Key)
{
case Avalonia.Input.Key.Enter:
await Confirmed();
break;
case Avalonia.Input.Key.Escape:
Cancel();
break;
}
}, Avalonia.Interactivity.RoutingStrategies.Tunnel);
}
public void SetDialogContent(string title, string content)
{
TitleBlock.Text = title;
MessageBlock.Text = content;
}
public void SetErrorMessage(string msg)
{
InputBox.BorderBrush = new SolidColorBrush(Colors.Red);
ErrorBlock.Text = msg;
ErrorBlock.IsVisible = true;
}
private void CancelBtn_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
Cancel();
}
private void Cancel()
{
if (!(onCancel?.Invoke()) ?? true)
{
DialogHost.Close(null);
}
}
private async void OKBtn_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
await Confirmed();
}
private async Task Confirmed()
{
if (onOK is not null)
{
if (!await onOK(InputBox.Text ?? ""))
{
DialogHost.Close(null);
}
}
else
DialogHost.Close(null);
}
}

View File

@@ -1,11 +1,10 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:avaloniaedit="https://github.com/avaloniaui/avaloniaedit" xmlns:avaloniaedit="https://github.com/avaloniaui/avaloniaedit"
xmlns:controls="using:Progrart.Controls"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Progrart.Pages.EditorPage"> x:Class="Progrart.Pages.EditorPage">
<avaloniaedit:TextEditor Name="CodeEditBox" Text="" SyntaxHighlighting="JavaScript" <controls:BaseEditor Name="CodeEditBox"/>
ShowLineNumbers="True"
FontFamily="Sarasa Mono Slab CL,Cascadia Code,Consolas,Menlo,Monospace"/>
</UserControl> </UserControl>

View File

@@ -3,9 +3,13 @@ using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using AvaloniaEdit;
using AvaloniaEdit.TextMate;
using Progrart.Controls.TabSystem; using Progrart.Controls.TabSystem;
using Progrart.Icons;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using TextMateSharp.Grammars;
namespace Progrart.Pages; namespace Progrart.Pages;
@@ -16,6 +20,7 @@ public partial class EditorPage : UserControl, ITabPage, IEditorPage
public EditorPage() public EditorPage()
{ {
InitializeComponent(); InitializeComponent();
} }
public void BindButton(TabButton button) public void BindButton(TabButton button)
@@ -30,11 +35,11 @@ public partial class EditorPage : UserControl, ITabPage, IEditorPage
} }
} }
public void Execute(ExecuteArguments? args = null) public void Execute(ExecuteArguments? args = null)
{ {
} }
public bool IsModified() public bool IsModified()
{ {
return false; return false;
} }
@@ -45,8 +50,16 @@ public partial class EditorPage : UserControl, ITabPage, IEditorPage
if (btn is not null) if (btn is not null)
{ {
btn.Title = file.Name; btn.Title = file.Name;
var path= file.TryGetLocalPath(); var path = file.TryGetLocalPath();
btn.TooltipText= path; btn.TooltipText = path;
}
{
var dotIndex = file.Name.LastIndexOf('.');
if (dotIndex >= 0)
{
var extension = file.Name[(dotIndex)..];
CodeEditBox.SetGrammerByExtension(extension);
}
} }
Task.Run(async () => Task.Run(async () =>
{ {

View File

@@ -1,26 +1,56 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:avaloniaedit="https://github.com/avaloniaui/avaloniaedit" xmlns:avaloniaedit="https://github.com/avaloniaui/avaloniaedit"
xmlns:controls="using:Progrart.Controls"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Progrart.ProgrartEditorPage"> x:Class="Progrart.ProgrartEditorPage">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.RowDefinitions>
<ColumnDefinition/> <RowDefinition/>
<ColumnDefinition Width="Auto"/> <RowDefinition Height="Auto"/>
<ColumnDefinition/> </Grid.RowDefinitions>
</Grid.ColumnDefinitions> <Grid>
<Grid.ColumnDefinitions>
<avaloniaedit:TextEditor Name="CodeEditBox" Text="" SyntaxHighlighting="JavaScript" <ColumnDefinition/>
ShowLineNumbers="True" <ColumnDefinition Width="Auto"/>
FontFamily="Sarasa Mono Slab CL,Cascadia Code,Consolas,Menlo,Monospace"/> <ColumnDefinition/>
<Grid Name="VerticalSplitterVisualElement"> </Grid.ColumnDefinitions>
<Border Width="2" Background="#8888"></Border> <controls:BaseEditor Name="CodeEditor"/>
<Grid Grid.Column="1" Name="VerticalSplitterVisualElement">
<Border Width="2" HorizontalAlignment="Center" Background="#4888"></Border>
</Grid>
<GridSplitter Grid.Column="1" Opacity="0.01"/>
<Grid Name="PreviewHolder" Grid.Column="2">
<controls:ImageViewer Name="PreviewImage"/>
</Grid>
</Grid> </Grid>
<GridSplitter Grid.Column="1"/> <Grid Grid.Row="1" Margin="0,5,0,5">
<Grid Name="PreviewHolder"> <Border Margin="16,8,16,0" Background="Transparent" BorderThickness="1,1,1,0" BorderBrush="#4888" CornerRadius="18">
</Border>
<Border Margin="16,8,16,0" Background="#2888" BorderBrush="Transparent" BorderThickness="1" CornerRadius="18">
<ScrollViewer Margin="16,0" HorizontalScrollBarVisibility="Auto">
<StackPanel Orientation="Horizontal" Margin="2">
<RadioButton GroupName="Layout0">
<PathIcon Data="F1 M 2.52 4.799999 C 2.36 4.799999 2.233333 4.846666 2.14 4.940001 C 2.046667 5.033333 2 5.153334 2 5.299999 C 2 5.446667 2.046667 5.566668 2.14 5.66 C 2.233333 5.753334 2.36 5.799999 2.52 5.799999 L 17.52 5.799999 C 17.653332 5.799999 17.766666 5.753334 17.859999 5.66 C 17.953331 5.566668 18 5.446667 18 5.299999 C 18 5.153334 17.953331 5.033333 17.859999 4.940001 C 17.766666 4.846666 17.653332 4.799999 17.52 4.799999 Z M 2.52 17.799999 C 2.36 17.799999 2.233333 17.846666 2.14 17.939999 C 2.046667 18.033333 2 18.153332 2 18.299999 C 2 18.446667 2.046667 18.566666 2.14 18.66 C 2.233333 18.753332 2.36 18.799999 2.52 18.799999 L 17.52 18.799999 C 17.653332 18.799999 17.766666 18.753332 17.859999 18.66 C 17.953331 18.566666 18 18.446667 18 18.299999 C 18 18.153332 17.953331 18.033333 17.859999 17.939999 C 17.766666 17.846666 17.653332 17.799999 17.52 17.799999 Z M 4 14.799999 C 4 15.36 4.193333 15.833333 4.58 16.219999 C 4.966666 16.606667 5.44 16.799999 6 16.799999 L 7 16.799999 C 7.559999 16.799999 8.033333 16.606667 8.42 16.219999 C 8.806666 15.833333 9 15.36 9 14.799999 L 9 8.799999 C 9 8.24 8.806666 7.766666 8.42 7.379999 C 8.033333 6.993334 7.559999 6.8 7 6.799999 L 6 6.799999 C 5.44 6.8 4.966666 6.993334 4.58 7.379999 C 4.193333 7.766666 4 8.24 4 8.799999 Z M 13 16.799999 C 12.439999 16.799999 11.966665 16.606667 11.58 16.219999 C 11.193333 15.833333 11 15.36 11 14.799999 L 11 8.799999 C 11 8.24 11.193333 7.766666 11.58 7.379999 C 11.966665 6.993334 12.439999 6.8 13 6.799999 L 14 6.799999 C 14.559999 6.8 15.033333 6.993334 15.42 7.379999 C 15.806666 7.766666 16 8.24 16 8.799999 L 16 14.799999 C 16 15.36 15.806666 15.833333 15.42 16.219999 C 15.033333 16.606667 14.559999 16.799999 14 16.799999 Z " VerticalAlignment="Center" HorizontalAlignment="Center" />
</RadioButton>
<RadioButton GroupName="Layout0">
<PathIcon Data="F1 M 3 19.279999 C 3 19.439999 3.046667 19.566666 3.14 19.66 C 3.233333 19.753332 3.353333 19.799999 3.5 19.799999 C 3.646667 19.799999 3.766666 19.753332 3.86 19.66 C 3.953333 19.566666 4 19.439999 4 19.279999 L 4 4.279999 C 4 4.146667 3.953333 4.033333 3.86 3.940001 C 3.766666 3.846668 3.646667 3.799999 3.5 3.799999 C 3.353333 3.799999 3.233333 3.846668 3.14 3.940001 C 3.046667 4.033333 3 4.146667 3 4.279999 Z M 16 19.279999 C 16 19.439999 16.046665 19.566666 16.139999 19.66 C 16.233332 19.753332 16.353333 19.799999 16.5 19.799999 C 16.646666 19.799999 16.766666 19.753332 16.859999 19.66 C 16.953333 19.566666 17 19.439999 17 19.279999 L 17 4.279999 C 17 4.146667 16.953333 4.033333 16.859999 3.940001 C 16.766666 3.846668 16.646666 3.799999 16.5 3.799999 C 16.353333 3.799999 16.233332 3.846668 16.139999 3.940001 C 16.046665 4.033333 16 4.146667 16 4.279999 Z M 13 17.799999 C 13.559999 17.799999 14.033333 17.606667 14.42 17.219999 C 14.806665 16.833332 14.999999 16.360001 15 15.799999 L 15 14.799999 C 14.999999 14.24 14.806665 13.766666 14.42 13.379999 C 14.033333 12.993333 13.559999 12.799999 13 12.799999 L 7 12.799999 C 6.44 12.799999 5.966666 12.993333 5.58 13.379999 C 5.193333 13.766666 5 14.24 5 14.799999 L 5 15.799999 C 5 16.360001 5.193333 16.833332 5.58 17.219999 C 5.966666 17.606667 6.44 17.799999 7 17.799999 Z M 15 8.799999 C 14.999999 9.360001 14.806665 9.833334 14.42 10.219999 C 14.033333 10.606667 13.559999 10.799999 13 10.799999 L 7 10.799999 C 6.44 10.799999 5.966666 10.606667 5.58 10.219999 C 5.193333 9.833334 5 9.360001 5 8.799999 L 5 7.799999 C 5 7.24 5.193333 6.766666 5.58 6.379999 C 5.966666 5.993333 6.44 5.799999 7 5.799999 L 13 5.799999 C 13.559999 5.799999 14.033333 5.993333 14.42 6.379999 C 14.806665 6.766666 14.999999 7.24 15 7.799999 Z " VerticalAlignment="Center" HorizontalAlignment="Center" />
</RadioButton>
<Border VerticalAlignment="Stretch" Background="#4888" Margin="5,2" Width="2"/>
<RadioButton GroupName="Layout1">
<PathIcon Data="F1 M 6 5.799999 L 7 5.799999 C 7.559999 5.799999 8.033333 5.993333 8.42 6.379999 C 8.806666 6.766666 9 7.24 9 7.799999 L 9 15.799999 C 9 16.360001 8.806666 16.833332 8.42 17.219999 C 8.033333 17.606667 7.559999 17.799999 7 17.799999 L 6 17.799999 C 5.44 17.799999 4.966666 17.606667 4.58 17.219999 C 4.193333 16.833332 4 16.360001 4 15.799999 L 4 7.799999 C 4 7.24 4.193333 6.766666 4.58 6.379999 C 4.966666 5.993333 5.44 5.799999 6 5.799999 Z M 5 7.799999 L 5 15.799999 C 5 16.066666 5.099999 16.299999 5.3 16.5 C 5.5 16.700001 5.733333 16.799999 6 16.799999 L 7 16.799999 C 7.266666 16.799999 7.5 16.700001 7.7 16.5 C 7.9 16.299999 8 16.066666 8 15.799999 L 8 7.799999 C 8 7.533333 7.9 7.299999 7.7 7.099999 C 7.5 6.9 7.266666 6.8 7 6.799999 L 6 6.799999 C 5.733333 6.8 5.5 6.9 5.3 7.099999 C 5.099999 7.299999 5 7.533333 5 7.799999 Z M 13 5.799999 C 12.439999 5.799999 11.966665 5.993333 11.58 6.379999 C 11.193333 6.766666 11 7.24 11 7.799999 L 11 15.799999 C 11 16.360001 11.193333 16.833332 11.58 17.219999 C 11.966665 17.606667 12.439999 17.799999 13 17.799999 L 14 17.799999 C 14.559999 17.799999 15.033333 17.606667 15.42 17.219999 C 15.806666 16.833332 16 16.360001 16 15.799999 L 16 7.799999 C 16 7.24 15.806666 6.766666 15.42 6.379999 C 15.033333 5.993333 14.559999 5.799999 14 5.799999 Z M 12 7.799999 C 12 7.533333 12.1 7.299999 12.3 7.099999 C 12.499999 6.9 12.733332 6.8 13 6.799999 L 14 6.799999 C 14.266666 6.8 14.5 6.9 14.7 7.099999 C 14.9 7.299999 14.999999 7.533333 15 7.799999 L 15 15.799999 C 14.999999 16.066666 14.9 16.299999 14.7 16.5 C 14.5 16.700001 14.266666 16.799999 14 16.799999 L 13 16.799999 C 12.733332 16.799999 12.499999 16.700001 12.3 16.5 C 12.1 16.299999 12 16.066666 12 15.799999 Z " VerticalAlignment="Center" HorizontalAlignment="Center" />
</RadioButton>
<RadioButton GroupName="Layout1">
<PathIcon Data="F1 M 6 4.799999 C 5.173333 4.799999 4.466666 5.093334 3.88 5.68 C 3.293333 6.266667 3 6.973333 3 7.799999 L 3 15.799999 C 3 16.626667 3.293333 17.333332 3.88 17.92 C 4.466666 18.506666 5.173333 18.799999 6 18.799999 L 14 18.799999 C 14.826666 18.799999 15.533332 18.506666 16.119999 17.92 C 16.706665 17.333332 17 16.626667 17 15.799999 L 17 7.799999 C 17 6.973333 16.706665 6.266667 16.119999 5.68 C 15.533332 5.093334 14.826666 4.799999 14 4.799999 Z M 4 7.799999 C 4 7.24 4.193333 6.766666 4.58 6.379999 C 4.966666 5.993333 5.44 5.799999 6 5.799999 L 14 5.799999 C 14.559999 5.799999 15.033333 5.993333 15.42 6.379999 C 15.806666 6.766666 16 7.24 16 7.799999 L 16 15.799999 C 16 16.360001 15.806666 16.833332 15.42 17.219999 C 15.033333 17.606667 14.559999 17.799999 14 17.799999 L 6 17.799999 C 5.44 17.799999 4.966666 17.606667 4.58 17.219999 C 4.193333 16.833332 4 16.360001 4 15.799999 Z M 8.84 9.639999 C 8.973333 9.506667 9.02 9.346667 8.98 9.16 C 8.94 8.973333 8.826666 8.86 8.639999 8.82 C 8.453333 8.78 8.293333 8.826666 8.16 8.959999 L 5.64 11.44 C 5.533333 11.546667 5.48 11.666666 5.48 11.799999 C 5.48 11.933332 5.533333 12.053333 5.64 12.16 L 8.16 14.639999 C 8.24 14.746666 8.353333 14.799999 8.5 14.799999 C 8.646667 14.799999 8.766666 14.753332 8.86 14.66 C 8.953333 14.566666 9 14.446667 9 14.299999 C 9 14.153334 8.946667 14.04 8.84 13.959999 L 6.72 11.799999 Z M 11.84 8.959999 C 11.759999 8.853333 11.646666 8.799999 11.5 8.799999 C 11.353333 8.799999 11.233333 8.846666 11.139999 8.94 C 11.046666 9.033334 11 9.153334 11 9.299999 C 11 9.446667 11.053333 9.56 11.16 9.639999 L 13.28 11.799999 L 11.16 13.959999 C 11.053333 14.04 11 14.153334 11 14.299999 C 11 14.446667 11.046666 14.566666 11.139999 14.66 C 11.233333 14.753332 11.353333 14.799999 11.5 14.799999 C 11.646666 14.799999 11.759999 14.746666 11.84 14.639999 L 14.36 12.16 C 14.466666 12.053333 14.52 11.933332 14.52 11.799999 C 14.52 11.666666 14.466666 11.546667 14.36 11.44 Z " VerticalAlignment="Center" HorizontalAlignment="Center" />
</RadioButton>
<RadioButton GroupName="Layout1">
<PathIcon Data="F1 M 7.52 4.799999 C 6.719999 4.799999 5.986666 4.986666 5.32 5.359999 C 4.653333 5.733334 4.113333 6.246666 3.7 6.9 C 3.286666 7.553333 3.053333 8.273333 3 9.059999 C 2.946666 9.846666 3.093333 10.586666 3.44 11.28 C 3.786666 11.973333 4.273333 12.54 4.9 12.98 C 5.526667 13.42 6.226666 13.679999 7 13.759999 L 7 14.759999 C 6.04 14.679999 5.173333 14.379999 4.4 13.859999 C 3.626667 13.339999 3.026667 12.66 2.6 11.82 C 2.173333 10.98 1.973333 10.086666 2 9.139999 C 2.026667 8.193333 2.28 7.313334 2.76 6.5 C 3.24 5.686666 3.886667 5.039999 4.7 4.559999 C 5.513333 4.08 6.393333 3.826668 7.34 3.799999 C 8.286667 3.773335 9.179999 3.973333 10.02 4.4 C 10.86 4.826666 11.539999 5.426666 12.059999 6.2 C 12.58 6.973333 12.879999 7.84 12.96 8.799999 L 11.96 8.799999 C 11.853333 7.653334 11.366667 6.7 10.5 5.94 C 9.633333 5.18 8.626666 4.799999 7.48 4.799999 Z M 10.52 9.799999 C 9.826666 9.799999 9.233333 10.046667 8.74 10.54 C 8.246666 11.033334 8 11.626667 8 12.32 L 8 17.279999 C 8 17.973333 8.246666 18.566666 8.74 19.059999 C 9.233333 19.553333 9.813333 19.799999 10.48 19.799999 L 15.52 19.799999 C 16.186666 19.799999 16.766666 19.553333 17.26 19.059999 C 17.753332 18.566666 18 17.986666 18 17.32 L 18 12.28 C 18 11.613334 17.753332 11.033334 17.26 10.54 C 16.766666 10.046667 16.173332 9.799999 15.48 9.799999 Z M 9 12.28 C 9 11.88 9.146666 11.533333 9.44 11.24 C 9.733334 10.946667 10.093333 10.799999 10.52 10.799999 L 15.52 10.799999 C 15.919998 10.799999 16.266665 10.946667 16.559999 11.24 C 16.853333 11.533333 17 11.893333 17 12.32 L 17 17.279999 C 17 17.706665 16.853333 18.066666 16.559999 18.359999 C 16.266665 18.653332 15.906665 18.799999 15.48 18.799999 L 10.52 18.799999 C 10.093333 18.799999 9.733334 18.653332 9.44 18.359999 C 9.146666 18.066666 9 17.706665 9 17.279999 Z " VerticalAlignment="Center" HorizontalAlignment="Center" />
</RadioButton>
</StackPanel>
</ScrollViewer>
</Border>
</Grid> </Grid>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -1,13 +1,75 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using Progrart.Controls.TabSystem;
using Progrart.Pages;
using System.IO;
using System.Threading.Tasks;
namespace Progrart; namespace Progrart;
public partial class ProgrartEditorPage : UserControl public partial class ProgrartEditorPage : UserControl, ITabPage,IEditorPage
{ {
public ProgrartEditorPage() IStorageFile? file = null;
TabButton? btn = null;
public ProgrartEditorPage()
{ {
InitializeComponent(); InitializeComponent();
} }
public void BindButton(TabButton button)
{
btn = button;
button.Title = "Editor Page";
if (file is not null)
{
btn.Title = file.Name;
var path = file.TryGetLocalPath();
btn.TooltipText = path;
}
}
public void Execute(ExecuteArguments? args = null)
{
}
public bool IsModified()
{
return false;
}
public void LoadDocument(IStorageFile file)
{
this.file = file;
if (btn is not null)
{
btn.Title = file.Name;
var path = file.TryGetLocalPath();
btn.TooltipText = path;
}
{
CodeEditor.SetGrammerByExtension(".js");
}
Task.Run(async () =>
{
using var stream = await file.OpenReadAsync();
using StreamReader sr = new StreamReader(stream);
var text = sr.ReadToEnd();
Dispatcher.UIThread.Invoke(() =>
{
CodeEditor.Text = text;
});
});
}
public void Save()
{
}
public void SetHost(TabHost host)
{
}
} }

View File

@@ -20,6 +20,8 @@
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets> <IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets> <PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="AvaloniaEdit.TextMate" />
<PackageReference Include="DialogHost.Avalonia" />
<PackageReference Include="PanAndZoom" /> <PackageReference Include="PanAndZoom" />
<!--<PackageReference Include="Devolutions.AvaloniaTheme.DevExpress" /> <!--<PackageReference Include="Devolutions.AvaloniaTheme.DevExpress" />
<PackageReference Include="Devolutions.AvaloniaTheme.MacOS" />--> <PackageReference Include="Devolutions.AvaloniaTheme.MacOS" />-->

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading;
using Progrart.Controls; using Progrart.Controls;
using Progrart.Core.JSExecution; using Progrart.Core.JSExecution;
using Progrart.Pages; using Progrart.Pages;
@@ -29,7 +30,7 @@ public partial class MainView : UserControl
WriteLine(e.Message); WriteLine(e.Message);
} }
}; };
Trace.Listeners.Add(new ConsoleLogger()); //Trace.Listeners.Add(new ConsoleLogger());
EditorProvider.setHost(MainTabHost); EditorProvider.setHost(MainTabHost);
BottomPanelToggle.IsCheckedChanged += (a, b) => BottomPanelToggle.IsCheckedChanged += (a, b) =>
{ {
@@ -47,7 +48,6 @@ public partial class MainView : UserControl
ContentGrid.RowDefinitions[2].MinHeight = 0; ContentGrid.RowDefinitions[2].MinHeight = 0;
} }
}; };
LeftPanelToggle.IsCheckedChanged += (a, b) => LeftPanelToggle.IsCheckedChanged += (a, b) =>
{ {
bool v = LeftPanelToggle.IsChecked == true; bool v = LeftPanelToggle.IsChecked == true;
@@ -92,11 +92,26 @@ public partial class MainView : UserControl
} }
public void Write(string message) public void Write(string message)
{ {
Output.Text += message; //Dispatcher.UIThread.Invoke(() =>
//Output.Text += message);
try
{
Output.Text += message;
}
catch (Exception)
{
}
} }
public void WriteLine(string message) public void WriteLine(string message)
{ {
Output.Text += $"{message}\n"; //Dispatcher.UIThread.Invoke(() =>);
try
{
Output.Text += $"{message}\n";
}
catch (Exception)
{
}
} }
private class ConsoleLogger : TraceListener private class ConsoleLogger : TraceListener
{ {