diff --git a/Directory.Packages.props b/Directory.Packages.props index 844c9e7..fb997d6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,11 +15,12 @@ - - + + \ No newline at end of file diff --git a/Progrart.Browser/Progrart.Browser.csproj b/Progrart.Browser/Progrart.Browser.csproj index b6c7274..5e25c81 100644 --- a/Progrart.Browser/Progrart.Browser.csproj +++ b/Progrart.Browser/Progrart.Browser.csproj @@ -3,11 +3,13 @@ net10.0-browser Exe true + true enable + diff --git a/Progrart.iOS/Info.plist b/Progrart.iOS/Info.plist index 6aeb579..a1ba03a 100644 --- a/Progrart.iOS/Info.plist +++ b/Progrart.iOS/Info.plist @@ -5,7 +5,7 @@ CFBundleDisplayName Progrart CFBundleIdentifier - io.creeperlv.CINT + io.creeperlv.Progrart CFBundleShortVersionString 1.0 CFBundleVersion diff --git a/Progrart/App.axaml.cs b/Progrart/App.axaml.cs index aa33770..de2c3d5 100644 --- a/Progrart/App.axaml.cs +++ b/Progrart/App.axaml.cs @@ -5,6 +5,7 @@ using Avalonia.Data.Core.Plugins; using System.Linq; using Avalonia.Markup.Xaml; using Progrart.Views; +using Progrart.Icons; namespace Progrart; @@ -23,7 +24,7 @@ public partial class App : Application // Avoid duplicate validations from both Avalonia and the CommunityToolkit. // More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins isDesktop = true; - + IconProvider.Register(new DefaultIconProvider()); DisableAvaloniaDataAnnotationValidation(); desktop.MainWindow = new MainWindow(); } diff --git a/Progrart/Controls/FileItem.axaml b/Progrart/Controls/FileItem.axaml index bd5f382..2bf510b 100644 --- a/Progrart/Controls/FileItem.axaml +++ b/Progrart/Controls/FileItem.axaml @@ -3,22 +3,35 @@ 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.FileItem"> + x:Class="Progrart.Controls.FileItem" HorizontalAlignment="Stretch"> - - - - - - - - - - - + + + + + + + diff --git a/Progrart/Controls/FileItem.axaml.cs b/Progrart/Controls/FileItem.axaml.cs index 26db25d..6c3134a 100644 --- a/Progrart/Controls/FileItem.axaml.cs +++ b/Progrart/Controls/FileItem.axaml.cs @@ -1,13 +1,70 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.Platform.Storage; +using Progrart.Icons; +using System.Threading.Tasks; namespace Progrart.Controls; public partial class FileItem : UserControl { - public FileItem() - { - InitializeComponent(); - } + IStorageItem currentItem; + bool isOpen = false; + public FileItem(IStorageItem storageItem) + { + InitializeComponent(); + currentItem = storageItem; + if (storageItem is IStorageFolder folder) + { + FolderIcon.IsVisible = true; + GenericFileIcon.IsVisible = false; + IconContainer.IsVisible = false; + } + else if (storageItem is IStorageFile file) + { + FolderIcon.IsVisible = false; + GenericFileIcon.IsVisible = true; + IconContainer.Children.Clear(); + var dotIndex = file.Name.LastIndexOf('.'); + if (dotIndex >= 0) + { + var extension = file.Name[(dotIndex + 1)..]; + if (IconProvider.TryGetIcon(extension, out var icon)) + { + GenericFileIcon.IsVisible = false; + IconContainer.Children.Add(icon); + } + } + IconContainer.IsVisible = true; + } + NameBlock.Text = storageItem.Name; + MainButton.DoubleTapped += async (_, _) => + { + if (currentItem is IStorageFolder folder) + { + if (isOpen) + { + RemoveAll(); + isOpen = false; + } + else + { + isOpen = true; + await LoadAll(folder); + } + } + }; + } + async Task LoadAll(IStorageFolder folder) + { + await foreach (var item in folder.GetItemsAsync()) + { + ItemContainer.Children.Add(new FileItem(item)); + } + } + void RemoveAll() + { + ItemContainer.Children.Clear(); + } } \ No newline at end of file diff --git a/Progrart/Controls/TabSystem/TabHost.axaml.cs b/Progrart/Controls/TabSystem/TabHost.axaml.cs index 9868d2f..5ceac6a 100644 --- a/Progrart/Controls/TabSystem/TabHost.axaml.cs +++ b/Progrart/Controls/TabSystem/TabHost.axaml.cs @@ -16,6 +16,7 @@ public partial class TabHost : UserControl this.TabContainer.Children.Add(button); if (page is Control pageControl) PageContainer.Children.Add(pageControl); + page.BindButton(button); SelectButton(button); } public void SelectButton(TabButton button) diff --git a/Progrart/Icons/DefaultIconProvider.cs b/Progrart/Icons/DefaultIconProvider.cs new file mode 100644 index 0000000..3727f6b --- /dev/null +++ b/Progrart/Icons/DefaultIconProvider.cs @@ -0,0 +1,44 @@ +using Avalonia.Controls; +using Avalonia.Media; +using System.Diagnostics.CodeAnalysis; + +namespace Progrart.Icons +{ + public class DefaultIconProvider : IIconProvider + { + public bool TryGetIcon(string name, [MaybeNullWhen(false)] out Control icon) + { + switch (name) + { + case "c": + case "c++": + case "cpp": + case "cxx": + case "cs": + case "h": + case "h++": + case "hpp": + case "hxx": + { + PathIcon _icon = new PathIcon(); + _icon.Data = PathGeometry.Parse("F1 M 12.96 5.48 C 13.013332 5.346666 13.013332 5.219999 12.96 5.1 C 12.906666 4.98 12.813333 4.893333 12.679999 4.84 C 12.546665 4.786667 12.419999 4.786667 12.3 4.84 C 12.179999 4.893333 12.093332 4.986668 12.04 5.119999 L 7.04 18.119999 C 6.96 18.306665 6.98 18.473333 7.1 18.619999 C 7.22 18.766666 7.38 18.826666 7.58 18.799999 C 7.779999 18.773333 7.906666 18.666666 7.96 18.48 Z M 5.84 7.919999 C 5.946666 8 6 8.113334 6 8.259999 C 6 8.406667 5.96 8.533333 5.88 8.639999 L 3.16 11.799999 L 5.88 14.959999 C 5.96 15.066667 5.993333 15.186666 5.98 15.32 C 5.966666 15.453333 5.906666 15.566667 5.8 15.66 C 5.693333 15.753333 5.573333 15.793333 5.44 15.779999 C 5.306666 15.766666 5.2 15.719999 5.12 15.639999 L 2.12 12.12 C 2.04 12.039999 2 11.933332 2 11.799999 C 2 11.666666 2.04 11.559999 2.12 11.48 L 5.12 7.959999 C 5.2 7.853333 5.313333 7.799999 5.46 7.799999 C 5.606667 7.799999 5.733333 7.839999 5.84 7.919999 Z M 14.16 16.16 C 14.053333 16.08 14 15.973333 14 15.839999 C 14 15.706667 14.04 15.586666 14.12 15.48 L 16.84 12.28 L 14.12 9.12 C 14.04 9.013333 14 8.893333 14 8.759999 C 14 8.626667 14.053333 8.513333 14.16 8.419999 C 14.266666 8.326667 14.393333 8.286667 14.54 8.299999 C 14.686666 8.313334 14.799999 8.373333 14.88 8.48 L 17.879999 11.959999 C 17.959999 12.066667 18 12.18 18 12.299999 C 18 12.42 17.959999 12.533333 17.879999 12.639999 L 14.88 16.119999 C 14.799999 16.226665 14.686666 16.286667 14.54 16.299999 C 14.393333 16.313332 14.266666 16.279999 14.16 16.199999 Z "); + icon = _icon; + return true; + } + case "sh": + case "bash": + case "ps1": + { + PathIcon _icon = new PathIcon(); + _icon.Data = PathGeometry.Parse("F1 M 5.64 10.959999 C 5.746666 10.853333 5.866666 10.799999 6 10.799999 C 6.133333 10.799999 6.253333 10.853333 6.36 10.959999 L 8.36 12.959999 C 8.466666 13.039999 8.52 13.153333 8.52 13.299999 C 8.52 13.446667 8.466666 13.559999 8.36 13.639999 L 6.36 15.639999 C 6.253333 15.746666 6.133333 15.799999 6 15.799999 C 5.866666 15.799999 5.746666 15.753333 5.64 15.66 C 5.533333 15.566667 5.48 15.446667 5.48 15.299999 C 5.48 15.153333 5.533333 15.04 5.64 14.959999 L 7.28 13.28 L 5.64 11.639999 C 5.533333 11.559999 5.48 11.446667 5.48 11.299999 C 5.48 11.153334 5.533333 11.04 5.64 10.959999 Z M 14.52 14.799999 L 9.52 14.799999 C 9.359999 14.799999 9.233333 14.846666 9.139999 14.94 C 9.046666 15.033333 9 15.153333 9 15.299999 C 9 15.446667 9.046666 15.566667 9.139999 15.66 C 9.233333 15.753333 9.346666 15.799999 9.48 15.799999 L 14.52 15.799999 C 14.653333 15.799999 14.766666 15.753333 14.86 15.66 C 14.953333 15.566667 14.999999 15.446667 15 15.299999 C 14.999999 15.153333 14.953333 15.033333 14.86 14.94 C 14.766666 14.846666 14.653333 14.799999 14.52 14.799999 Z M 3 7.28 C 3 6.613334 3.246666 6.033334 3.74 5.539999 C 4.233333 5.046665 4.813333 4.799999 5.48 4.799999 L 14.48 4.799999 C 15.173332 4.799999 15.766665 5.046665 16.26 5.539999 C 16.753334 6.033334 17 6.626667 17 7.32 L 17 16.279999 C 17 16.973333 16.753334 17.566666 16.26 18.059999 C 15.766665 18.553333 15.173332 18.799999 14.48 18.799999 L 5.48 18.799999 C 4.813333 18.799999 4.233333 18.553333 3.74 18.059999 C 3.246666 17.566666 3 16.973333 3 16.279999 Z M 16 7.799999 L 16 7.28 C 16 6.88 15.853333 6.533334 15.559999 6.24 C 15.266665 5.946667 14.906666 5.799999 14.48 5.799999 L 5.48 5.799999 C 5.08 5.799999 4.733334 5.946667 4.44 6.24 C 4.146667 6.533334 4 6.893333 4 7.32 L 4 7.799999 Z M 4 8.799999 L 4 16.279999 C 4 16.706665 4.146667 17.066666 4.44 17.359999 C 4.733334 17.653332 5.08 17.799999 5.48 17.799999 L 14.48 17.799999 C 14.906666 17.799999 15.266665 17.653332 15.559999 17.359999 C 15.853333 17.066666 16 16.706665 16 16.279999 L 16 8.799999 Z "); + icon = _icon; + return true; + } + default: + break; + } + icon = null; + return false; + } + } +} \ No newline at end of file diff --git a/Progrart/Icons/IIconProvider.cs b/Progrart/Icons/IIconProvider.cs new file mode 100644 index 0000000..82bf3ee --- /dev/null +++ b/Progrart/Icons/IIconProvider.cs @@ -0,0 +1,10 @@ +using Avalonia.Controls; +using System.Diagnostics.CodeAnalysis; + +namespace Progrart.Icons +{ + public interface IIconProvider + { + bool TryGetIcon(string name, [MaybeNullWhen(false)] out Control icon); + } +} \ No newline at end of file diff --git a/Progrart/Icons/IconProvider.cs b/Progrart/Icons/IconProvider.cs new file mode 100644 index 0000000..255c8d7 --- /dev/null +++ b/Progrart/Icons/IconProvider.cs @@ -0,0 +1,24 @@ +using Avalonia.Controls; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Progrart.Icons +{ + public static class IconProvider + { + static List providers = new List(); + public static void Register(IIconProvider provider) + { + providers.Add(provider); + } + public static bool TryGetIcon(string name, [MaybeNullWhen(false)] out Control icon) + { + foreach (var provider in providers) + { + if (provider.TryGetIcon(name, out icon)) return true; + } + icon = null; + return false; + } + } +} \ No newline at end of file diff --git a/Progrart/Progrart.csproj b/Progrart/Progrart.csproj index a33ae6a..25b156a 100644 --- a/Progrart/Progrart.csproj +++ b/Progrart/Progrart.csproj @@ -20,8 +20,8 @@ None All - - + diff --git a/Progrart/Views/MainView.axaml b/Progrart/Views/MainView.axaml index 42a558e..1d483b7 100644 --- a/Progrart/Views/MainView.axaml +++ b/Progrart/Views/MainView.axaml @@ -24,8 +24,8 @@ - - @@ -65,9 +65,11 @@ - File Explorer - - + + File Explorer + + + @@ -82,8 +84,8 @@ - - + + - + All @@ -123,24 +125,25 @@ - + - - + - Output + + + Output + diff --git a/Progrart/Views/MainView.axaml.cs b/Progrart/Views/MainView.axaml.cs index 7b4647f..e4af9c8 100644 --- a/Progrart/Views/MainView.axaml.cs +++ b/Progrart/Views/MainView.axaml.cs @@ -1,4 +1,6 @@ using Avalonia.Controls; +using Avalonia.Platform.Storage; +using Progrart.Controls; using Progrart.Core.JSExecution; using Progrart.Pages; using System; @@ -31,10 +33,19 @@ public partial class MainView : UserControl BottomPanelToggle.IsCheckedChanged += (a, b) => { - BottomPanel.IsVisible = BottomPanelToggle.IsChecked == true; - SplitterVisual.IsVisible = BottomPanelToggle.IsChecked == true; - Splitter.IsVisible = BottomPanelToggle.IsChecked == true; + bool v = BottomPanelToggle.IsChecked == true; + BottomPanel.IsVisible = v; + SplitterVisual.IsVisible = v; + Splitter.IsVisible = v; ContentGrid.RowDefinitions[2].Height = GridLength.Auto; + if (v) + { + ContentGrid.RowDefinitions[2].MinHeight = 48; + } + else + { + ContentGrid.RowDefinitions[2].MinHeight = 0; + } }; LeftPanelToggle.IsCheckedChanged += (a, b) => @@ -53,6 +64,34 @@ public partial class MainView : UserControl { MainTabHost.AddPage(new AboutPage()); }; + OpenProjectMenuItem.Click += async (_, _) => + { + var topLevel = TopLevel.GetTopLevel(this); + + if (topLevel == null) return; + + // Open the folder picker + var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + Title = "Select Folder", + AllowMultiple = false + }); + + if (folders.Count >= 1) + { + // Get the first selected folder path + // Note: TryGetLocalPath() returns null if the file isn't on a local disk (e.g., cloud storage) + var folderPath = folders[0].TryGetLocalPath(); + var folder = folders[0]; + FileContainer.Children.Add(new FileItem(folder)); + if (folderPath != null) + { + // Do something with the path + System.Diagnostics.Debug.WriteLine($"Picked: {folderPath}"); + } + } + }; + LeftPanelToggle.IsChecked = true; } public void Write(string message) {