Implemented editor providers.

This commit is contained in:
Creeper Lv
2025-12-18 01:28:15 +11:00
parent daa2a74e71
commit 76caa0d644
8 changed files with 135 additions and 20 deletions

View File

@@ -6,6 +6,7 @@ using System.Linq;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Progrart.Views; using Progrart.Views;
using Progrart.Icons; using Progrart.Icons;
using Progrart.Pages;
namespace Progrart; namespace Progrart;
@@ -19,12 +20,22 @@ public partial class App : Application
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()
{ {
IconProvider.Register(new DefaultIconProvider());
EditorProvider.Register("text", "Default Text Editor", typeof(EditorPage));
EditorProvider.BindFileType("cs", "text");
EditorProvider.BindFileType("c", "text");
EditorProvider.BindFileType("cpp", "text");
EditorProvider.BindFileType("h", "text");
EditorProvider.BindFileType("hpp", "text");
EditorProvider.BindFileType("txt", "text");
EditorProvider.BindFileType("cpp", "text");
EditorProvider.BindFileType("json", "text");
EditorProvider.BindFileType("sh", "text");
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
// Avoid duplicate validations from both Avalonia and the CommunityToolkit. // Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins // More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
isDesktop = true; isDesktop = true;
IconProvider.Register(new DefaultIconProvider());
DisableAvaloniaDataAnnotationValidation(); DisableAvaloniaDataAnnotationValidation();
desktop.MainWindow = new MainWindow(); desktop.MainWindow = new MainWindow();
} }

View File

@@ -10,7 +10,7 @@
<Button.ContextMenu> <Button.ContextMenu>
<ContextMenu> <ContextMenu>
<MenuItem Header="_Open"/> <MenuItem Header="_Open" Name="OpenFileMenuItem"/>
<MenuItem Header="_Delete"/> <MenuItem Header="_Delete"/>
</ContextMenu> </ContextMenu>
</Button.ContextMenu> </Button.ContextMenu>

View File

@@ -2,7 +2,9 @@ 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 Progrart.Controls.TabSystem;
using Progrart.Icons; using Progrart.Icons;
using Progrart.Pages;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Progrart.Controls; namespace Progrart.Controls;
@@ -11,6 +13,7 @@ public partial class FileItem : UserControl
{ {
IStorageItem currentItem; IStorageItem currentItem;
bool isOpen = false; bool isOpen = false;
string extension = "";
public FileItem(IStorageItem storageItem) public FileItem(IStorageItem storageItem)
{ {
InitializeComponent(); InitializeComponent();
@@ -29,7 +32,7 @@ public partial class FileItem : UserControl
var dotIndex = file.Name.LastIndexOf('.'); var dotIndex = file.Name.LastIndexOf('.');
if (dotIndex >= 0) if (dotIndex >= 0)
{ {
var extension = file.Name[(dotIndex + 1)..]; extension = file.Name[(dotIndex + 1)..];
if (IconProvider.TryGetIcon(extension, out var icon)) if (IconProvider.TryGetIcon(extension, out var icon))
{ {
GenericFileIcon.IsVisible = false; GenericFileIcon.IsVisible = false;
@@ -41,6 +44,16 @@ public partial class FileItem : UserControl
NameBlock.Text = storageItem.Name; NameBlock.Text = storageItem.Name;
MainButton.DoubleTapped += async (_, _) => MainButton.DoubleTapped += async (_, _) =>
{ {
await OpenItem();
};
OpenFileMenuItem.Click += async (a, b) =>
{
await OpenItem();
};
}
async Task OpenItem()
{
if (currentItem is IStorageFolder folder) if (currentItem is IStorageFolder folder)
{ {
if (isOpen) if (isOpen)
@@ -54,7 +67,22 @@ public partial class FileItem : UserControl
await LoadAll(folder); await LoadAll(folder);
} }
} }
}; else
if (currentItem is IStorageFile file)
{
if (EditorProvider.TryGetEditor(extension, out var page))
{
if (page is ITabPage editor)
{
if (page is IEditorPage editor_page)
{
editor_page.LoadDocument(file);
}
EditorProvider.OpenEditor(editor);
}
}
}
} }
async Task LoadAll(IStorageFolder folder) async Task LoadAll(IStorageFolder folder)
{ {

View File

@@ -9,7 +9,5 @@ namespace Progrart.Controls.TabSystem
void SetHost(TabHost host); void SetHost(TabHost host);
void BindButton(TabButton button); void BindButton(TabButton button);
bool IsModified(); bool IsModified();
void Save();
void Execute();
} }
} }

View File

@@ -5,7 +5,7 @@
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="CodePane" Text="" SyntaxHighlighting="JavaScript" <avaloniaedit:TextEditor Name="CodeEditBox" Text="" SyntaxHighlighting="JavaScript"
ShowLineNumbers="True" ShowLineNumbers="True"
FontFamily="Cascadia Code,Consolas,Menlo,Monospace"/> FontFamily="Sarasa Mono Slab CL,Cascadia Code,Consolas,Menlo,Monospace"/>
</UserControl> </UserControl>

View File

@@ -1,11 +1,15 @@
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.Controls.TabSystem;
using System.IO;
using System.Threading.Tasks;
namespace Progrart.Pages; namespace Progrart.Pages;
public partial class EditorPage : UserControl, ITabPage public partial class EditorPage : UserControl, ITabPage, IEditorPage
{ {
public EditorPage() public EditorPage()
{ {
@@ -14,7 +18,7 @@ public partial class EditorPage : UserControl, ITabPage
public void BindButton(TabButton button) public void BindButton(TabButton button)
{ {
button.Title="Editor Page"; button.Title = "Editor Page";
} }
public void Execute() public void Execute()
@@ -26,6 +30,20 @@ public partial class EditorPage : UserControl, ITabPage
return false; return false;
} }
public void LoadDocument(IStorageFile file)
{
Task.Run(async () =>
{
using var stream = await file.OpenReadAsync();
using StreamReader sr = new StreamReader(stream);
var text = sr.ReadToEnd();
Dispatcher.UIThread.Invoke(() =>
{
CodeEditBox.Text = text;
});
});
}
public void Save() public void Save()
{ {
} }

View File

@@ -0,0 +1,60 @@
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Progrart.Controls.TabSystem;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace Progrart.Pages
{
static public class EditorProvider
{
static Dictionary<string, string> Names = new();
static Dictionary<string, string> ExtensionMapping = new();
static Dictionary<string, Type> EditorTypes = new();
static TabHost? currentHost = null;
public static void setHost(TabHost host)
{
currentHost = host;
}
public static void Register(string id, string name, Type t)
{
Names[id] = name;
EditorTypes[id] = t;
}
public static void BindFileType(string type, string id)
{
ExtensionMapping[type] = id;
}
public static void OpenEditor(ITabPage page)
{
currentHost?.AddPage(page);
}
public static bool TryGetEditor(string extension, [MaybeNullWhen(false)] out Control editorPage)
{
if (ExtensionMapping.TryGetValue(extension.ToLower(), out var id))
{
if (EditorTypes.TryGetValue(id, out var editorType))
{
var obj = Activator.CreateInstance(editorType);
if (obj is Control control)
{
editorPage = control;
return true;
}
}
}
editorPage = null;
return false;
}
}
public interface IEditorPage
{
void LoadDocument(IStorageFile file);
void Save();
void Execute();
}
}

View File

@@ -30,7 +30,7 @@ public partial class MainView : UserControl
} }
}; };
Trace.Listeners.Add(new ConsoleLogger()); Trace.Listeners.Add(new ConsoleLogger());
EditorProvider.setHost(MainTabHost);
BottomPanelToggle.IsCheckedChanged += (a, b) => BottomPanelToggle.IsCheckedChanged += (a, b) =>
{ {
bool v = BottomPanelToggle.IsChecked == true; bool v = BottomPanelToggle.IsChecked == true;