feat: Implement LogViewer control and integrate into EditPage
- Added LogViewer control to display log messages with filtering options. - Integrated LogViewer into EditPage for better log management. - Updated EngineEditorWindow to navigate to EditPage. - Enhanced Logger implementation for improved performance and stack trace capturing. - Introduced PathUtility for path normalization. - Refactored AssetManager to correct shader asset type naming. - Removed obsolete AssetHandlerRegistryTests and cleaned up related tests. - Updated ImportCoordinatorTests for streamlined asset import process.
This commit is contained in:
@@ -54,7 +54,7 @@ internal static class ActivationHandler
|
||||
|
||||
public static ValueTask HandleAsync(LaunchArguments args)
|
||||
{
|
||||
var opts = new AllocationManagerInitOpts
|
||||
var opts = new AllocationManagerDesc
|
||||
{
|
||||
ArenaCapacity = 1024 * 1024 * 1024, // 1 GB. Arena using virtual memory, so this is just a reservation and won't actually consume physical memory until used.
|
||||
StackCapacity = 1024 * 1024 * 32, // 32 MB. Stack using virtual memory, so this is just a reservation and won't actually consume physical memory until used.
|
||||
@@ -65,7 +65,7 @@ internal static class ActivationHandler
|
||||
|
||||
AllocationManager.Initialize(opts);
|
||||
|
||||
//App.GetService<EngineCore>();
|
||||
App.GetService<EngineCore>();
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -65,10 +65,13 @@ public partial class App : Application
|
||||
services.AddSingleton<IInspectorService, InspectorService>();
|
||||
services.AddSingleton<IPreviewService, PreviewService>();
|
||||
services.AddSingleton<IAssetRegistry, AssetRegistry>();
|
||||
services.AddSingleton<IContentProvider, EditorContentProvider>();
|
||||
|
||||
services.AddSingleton<EngineCore>();
|
||||
|
||||
services.AddSingleton<EngineEditorViewModel>();
|
||||
|
||||
services.AddTransient<ProjectBrowserViewModel>();
|
||||
services.AddTransient<ContentBrowserViewModel>();
|
||||
|
||||
// TODO: Use source generators to generate this code at compile time instead of using reflection at runtime.
|
||||
foreach (var type in TypeCache.GetTypes())
|
||||
|
||||
@@ -141,6 +141,9 @@
|
||||
<None Update="Assets\icon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Page Update="Views\Controls\LogViewer.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Views\Windows\EngineEditorWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
|
||||
@@ -1,27 +1,72 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Engine;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Ghost.Editor.Models;
|
||||
|
||||
internal class ExplorerItem(string name, string path, bool isDirectory)
|
||||
internal partial class ExplorerItem : ObservableObject
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
} = name;
|
||||
}
|
||||
|
||||
public string FullName
|
||||
public string Path
|
||||
{
|
||||
get;
|
||||
} = path;
|
||||
}
|
||||
|
||||
public bool IsDirectory
|
||||
{
|
||||
get;
|
||||
} = isDirectory;
|
||||
}
|
||||
|
||||
public ObservableCollection<ExplorerItem>? Children
|
||||
|
||||
public AssetType AssetType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<ExplorerItem>? Children
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string IconGlyph
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public ExplorerItem(string name, string path, bool isDirectory, AssetType assetType = AssetType.Unknown)
|
||||
{
|
||||
Name = name;
|
||||
Path = PathUtility.Normalize(path);
|
||||
IsDirectory = isDirectory;
|
||||
AssetType = assetType;
|
||||
|
||||
if (IsDirectory)
|
||||
{
|
||||
IconGlyph = "\uE8B7"; // Folder icon
|
||||
}
|
||||
else
|
||||
{
|
||||
IconGlyph = GetIconGlyphForAssetType(assetType);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetIconGlyphForAssetType(AssetType assetType)
|
||||
{
|
||||
return assetType switch
|
||||
{
|
||||
AssetType.Texture => "\uEB9F", // Image icon
|
||||
AssetType.Material => "\uE943", // Document/Material
|
||||
AssetType.Shader => "\uE9E9", // Code
|
||||
AssetType.Mesh => "\uE8B3", // 3D icon
|
||||
AssetType.Audio => "\uE8D6", // Audio
|
||||
_ => "\uE7C3" // Default file icon
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,18 @@
|
||||
<Setter Property="Margin" Value="0,2" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="VerticalStrongDivider" TargetType="Border">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource ControlElevationBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1,0,0,0" />
|
||||
<Setter Property="Margin" Value="2,0" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="HorizontalStrongDivider" TargetType="Border">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource ControlElevationBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="0,1,0,0" />
|
||||
<Setter Property="Margin" Value="0,2" />
|
||||
</Style>
|
||||
|
||||
<!-- Named Resource -->
|
||||
<x:Double x:Key="ToolbarIconSize">12</x:Double>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -12,7 +12,7 @@ public partial class ExplorerItemToIconUriConverter : IValueConverter
|
||||
{
|
||||
if (value is ExplorerItem item)
|
||||
{
|
||||
var path = _previewService.GetIconPath(item.FullName, item.IsDirectory, IconSize.Small);
|
||||
var path = _previewService.GetIconPath(item.Path, item.IsDirectory, IconSize.Small);
|
||||
return new Uri(path);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ghost.Editor.Core;
|
||||
using Ghost.Editor.Core.Contracts;
|
||||
using Ghost.Editor.Core.Utilities;
|
||||
using Ghost.Editor.Models;
|
||||
using Ghost.Editor.Core.AssetHandler;
|
||||
using System.Collections.ObjectModel;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Ghost.Engine;
|
||||
using Ghost.Core.Utilities;
|
||||
|
||||
namespace Ghost.Editor.ViewModels.Controls;
|
||||
|
||||
internal partial class ContentBrowserViewModel : ObservableObject
|
||||
{
|
||||
private readonly IInspectorService _inspectorService;
|
||||
private readonly IAssetRegistry _assetRegistry;
|
||||
private readonly DispatcherQueue _dispatcherQueue;
|
||||
|
||||
private readonly Dictionary<string, ExplorerItem> _pathToDirectoryItemMap = new();
|
||||
private ExplorerItem? _selectedItem;
|
||||
|
||||
public ObservableCollection<ExplorerItem> Directories
|
||||
{
|
||||
get;
|
||||
} = new();
|
||||
|
||||
public ObservableCollection<ExplorerItem> Files
|
||||
{
|
||||
get;
|
||||
} = new();
|
||||
|
||||
public ExplorerItem? SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set
|
||||
{
|
||||
// TODO: Resolve inspector by reading metadata from selected asset
|
||||
_selectedItem = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string CurrentDirectoryPath
|
||||
{
|
||||
get;
|
||||
set => field = PathUtility.Normalize(value);
|
||||
} = string.Empty;
|
||||
|
||||
public ContentBrowserViewModel(IInspectorService inspectorService, IAssetRegistry assetRegistry)
|
||||
{
|
||||
_inspectorService = inspectorService;
|
||||
_assetRegistry = assetRegistry;
|
||||
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
var assetsRootItem = new ExplorerItem(EditorApplication.ASSETS_FOLDER_NAME, EditorApplication.AssetsFolderPath, true);
|
||||
LoadSubFolderRecursive(assetsRootItem);
|
||||
|
||||
Directories.Add(assetsRootItem);
|
||||
|
||||
_assetRegistry.OnAssetChanged += OnAssetChanged;
|
||||
}
|
||||
|
||||
private void OnAssetChanged(object? sender, AssetChangedEventArgs e)
|
||||
{
|
||||
if (Path.GetExtension(e.AssetPath) == FileExtensions.META_FILE_EXTENSION)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var fullPath = PathUtility.Normalize(Path.Combine(EditorApplication.AssetsFolderPath, e.AssetPath));
|
||||
var dirPath = PathUtility.Normalize(Path.GetDirectoryName(fullPath));
|
||||
|
||||
if (string.Equals(dirPath, CurrentDirectoryPath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
if (e.ChangeType == AssetChangeType.Created || e.ChangeType == AssetChangeType.Renamed)
|
||||
{
|
||||
if (e.ChangeType == AssetChangeType.Renamed && e.OldAssetPath != null)
|
||||
{
|
||||
var oldFullPath = PathUtility.Normalize(Path.Combine(EditorApplication.AssetsFolderPath, e.OldAssetPath));
|
||||
var oldItem = Files.FirstOrDefault(f => string.Equals(f.Path, oldFullPath, StringComparison.OrdinalIgnoreCase));
|
||||
if (oldItem != null) Files.Remove(oldItem);
|
||||
}
|
||||
|
||||
if (!Files.Any(f => string.Equals(f.Path, fullPath, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var isDir = Directory.Exists(fullPath);
|
||||
AssetType assetType = AssetType.Unknown;
|
||||
if (!isDir)
|
||||
{
|
||||
var ext = Path.GetExtension(fullPath);
|
||||
assetType = AssetHandlerRegistry.GetAssetTypeByExtension(ext);
|
||||
}
|
||||
Files.Add(new ExplorerItem(Path.GetFileName(fullPath), fullPath, isDir, assetType));
|
||||
}
|
||||
}
|
||||
else if (e.ChangeType == AssetChangeType.Deleted)
|
||||
{
|
||||
var item = Files.FirstOrDefault(f => string.Equals(f.Path, fullPath, StringComparison.OrdinalIgnoreCase));
|
||||
if (item != null)
|
||||
{
|
||||
Files.Remove(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadSubFolderRecursive(ExplorerItem parentItem)
|
||||
{
|
||||
foreach (var directory in Directory.EnumerateDirectories(parentItem.Path))
|
||||
{
|
||||
var item = new ExplorerItem(Path.GetFileName(directory), directory, true);
|
||||
LoadSubFolderRecursive(item);
|
||||
|
||||
_pathToDirectoryItemMap[directory] = item;
|
||||
|
||||
parentItem.Children ??= new();
|
||||
parentItem.Children.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
internal void NavigateToDirectory(string? path)
|
||||
{
|
||||
Files.Clear();
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var directory in Directory.EnumerateDirectories(path))
|
||||
{
|
||||
var directoryItem = new ExplorerItem(Path.GetFileName(directory), directory, true);
|
||||
Files.Add(directoryItem);
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(path))
|
||||
{
|
||||
if (Path.GetExtension(file) == FileExtensions.META_FILE_EXTENSION)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(file);
|
||||
var assetType = AssetHandlerRegistry.GetAssetTypeByExtension(ext);
|
||||
|
||||
var fileItem = new ExplorerItem(Path.GetFileName(file), file, false, assetType);
|
||||
Files.Add(fileItem);
|
||||
}
|
||||
|
||||
CurrentDirectoryPath = Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
internal (ExplorerItem?, int) OpenSelected()
|
||||
{
|
||||
if (SelectedItem == null)
|
||||
{
|
||||
return (null, 0);
|
||||
}
|
||||
|
||||
if (SelectedItem.IsDirectory)
|
||||
{
|
||||
NavigateToDirectory(SelectedItem.Path);
|
||||
SelectedItem = _pathToDirectoryItemMap[SelectedItem.Path];
|
||||
return (SelectedItem, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// _assetRegistry.OpenAsset(SelectedItem.FullName);
|
||||
return (null, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ghost.Editor.Core;
|
||||
using Ghost.Editor.Core.Contracts;
|
||||
using Ghost.Editor.Core.Utilities;
|
||||
using Ghost.Editor.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Ghost.Editor.ViewModels.Controls;
|
||||
|
||||
internal partial class ProjectBrowserViewModel : ObservableObject
|
||||
{
|
||||
private readonly IInspectorService _inspectorService;
|
||||
private readonly IAssetRegistry _assetRegistry;
|
||||
|
||||
private readonly Dictionary<string, ExplorerItem> _pathToDirectoryItemMap = new();
|
||||
private ExplorerItem? _selectedItem;
|
||||
|
||||
public ObservableCollection<ExplorerItem> Directories
|
||||
{
|
||||
get;
|
||||
} = new();
|
||||
|
||||
public ObservableCollection<ExplorerItem> Files
|
||||
{
|
||||
get;
|
||||
} = new();
|
||||
|
||||
public ExplorerItem? SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set
|
||||
{
|
||||
// TODO: Resolve inspector by reading metadata from selected asset
|
||||
_selectedItem = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string CurrentDirectoryPath
|
||||
{
|
||||
get; set;
|
||||
} = string.Empty;
|
||||
|
||||
public ProjectBrowserViewModel(IInspectorService inspectorService, IAssetRegistry assetRegistry)
|
||||
{
|
||||
_inspectorService = inspectorService;
|
||||
_assetRegistry = assetRegistry;
|
||||
|
||||
var assetsRootItem = new ExplorerItem(EditorApplication.ASSETS_FOLDER_NAME, Path.Combine(EditorApplication.ProjectPath, EditorApplication.ASSETS_FOLDER_NAME), true);
|
||||
LoadSubFolderRecursive(assetsRootItem);
|
||||
|
||||
Directories.Add(assetsRootItem);
|
||||
}
|
||||
|
||||
private void LoadSubFolderRecursive(ExplorerItem parentItem)
|
||||
{
|
||||
foreach (var directory in Directory.EnumerateDirectories(parentItem.FullName))
|
||||
{
|
||||
var item = new ExplorerItem(Path.GetFileName(directory), directory, true);
|
||||
LoadSubFolderRecursive(item);
|
||||
|
||||
_pathToDirectoryItemMap[directory] = item;
|
||||
|
||||
parentItem.Children ??= new();
|
||||
parentItem.Children.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
internal void NavigateToDirectory(string? path)
|
||||
{
|
||||
Files.Clear();
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var directory in Directory.EnumerateDirectories(path))
|
||||
{
|
||||
var directoryItem = new ExplorerItem(Path.GetFileName(directory), directory, true);
|
||||
Files.Add(directoryItem);
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(path))
|
||||
{
|
||||
if (Path.GetExtension(file) == FileExtensions.META_FILE_EXTENSION)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var fileItem = new ExplorerItem(Path.GetFileName(file), file, false);
|
||||
Files.Add(fileItem);
|
||||
}
|
||||
|
||||
CurrentDirectoryPath = path;
|
||||
}
|
||||
|
||||
internal (ExplorerItem?, int) OpenSelected()
|
||||
{
|
||||
if (SelectedItem == null)
|
||||
{
|
||||
return (null, 0);
|
||||
}
|
||||
|
||||
if (SelectedItem.IsDirectory)
|
||||
{
|
||||
NavigateToDirectory(SelectedItem.FullName);
|
||||
SelectedItem = _pathToDirectoryItemMap[SelectedItem.FullName];
|
||||
return (SelectedItem, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// _assetRegistry.OpenAsset(SelectedItem.FullName);
|
||||
return (null, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,6 @@
|
||||
xmlns:sys="using:System"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<converter:ExplorerItemToIconUriConverter x:Key="ExplorerItemToIconUriConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid MinHeight="50">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
@@ -145,7 +141,7 @@
|
||||
IsDoubleTapEnabled="True"
|
||||
ItemsSource="{x:Bind ViewModel.Files}"
|
||||
SelectionChanged="PART_FilesView_SelectionChanged"
|
||||
SelectionMode="Single">
|
||||
SelectionMode="Extended">
|
||||
<GridView.ItemTemplate>
|
||||
<DataTemplate x:DataType="model:ExplorerItem">
|
||||
<ItemContainer>
|
||||
@@ -171,11 +167,7 @@
|
||||
</Grid.ContextFlyout>
|
||||
|
||||
<community:ConstrainedBox Grid.Row="0" AspectRatio="1:1">
|
||||
<Image HorizontalAlignment="Center">
|
||||
<Image.Source>
|
||||
<BitmapImage DecodePixelWidth="48" UriSource="{x:Bind Converter={StaticResource ExplorerItemToIconUriConverter}}" />
|
||||
</Image.Source>
|
||||
</Image>
|
||||
<FontIcon FontSize="36" Glyph="{x:Bind IconGlyph}" />
|
||||
</community:ConstrainedBox>
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
|
||||
@@ -19,7 +19,7 @@ internal sealed partial class ContentBrowser : UserControl
|
||||
private readonly IInspectorService _inspectorService;
|
||||
private bool _isUpdatingSelection = false;
|
||||
|
||||
public ProjectBrowserViewModel ViewModel
|
||||
public ContentBrowserViewModel ViewModel
|
||||
{
|
||||
get;
|
||||
}
|
||||
@@ -27,7 +27,7 @@ internal sealed partial class ContentBrowser : UserControl
|
||||
public ContentBrowser()
|
||||
{
|
||||
_inspectorService = App.GetService<IInspectorService>();
|
||||
ViewModel = App.GetService<ProjectBrowserViewModel>();
|
||||
ViewModel = App.GetService<ContentBrowserViewModel>();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
@@ -64,7 +64,7 @@ internal sealed partial class ContentBrowser : UserControl
|
||||
|
||||
private void _inspectorService_OnSelectionChanged(object? sender, InspectorSelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Source is not ProjectBrowserViewModel)
|
||||
if (e.Source is not ContentBrowserViewModel)
|
||||
{
|
||||
PART_FilesView.DeselectAll();
|
||||
PART_DirectoriesView.SelectedNodes.Clear();
|
||||
@@ -84,7 +84,7 @@ internal sealed partial class ContentBrowser : UserControl
|
||||
if (args.AddedItems.Count > 0 && args.AddedItems[0] is ExplorerItem selectedItem)
|
||||
{
|
||||
ViewModel.SelectedItem = selectedItem;
|
||||
ViewModel.NavigateToDirectory(selectedItem.FullName);
|
||||
ViewModel.NavigateToDirectory(selectedItem.Path);
|
||||
}
|
||||
|
||||
_isUpdatingSelection = false;
|
||||
|
||||
166
src/Editor/Ghost.Editor/Views/Controls/LogViewer.xaml
Normal file
166
src/Editor/Ghost.Editor/Views/Controls/LogViewer.xaml
Normal file
@@ -0,0 +1,166 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="Ghost.Editor.Views.Controls.LogViewer"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fic="using:FluentIcons.WinUI"
|
||||
xmlns:local="using:Ghost.Editor.Views.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<local:LogLevelToColorConverter x:Key="LogLevelToColorConverter" />
|
||||
<local:LogLevelToSymbolConverter x:Key="LogLevelToSymbolConverter" />
|
||||
|
||||
<DataTemplate x:Key="LogItemTemplate">
|
||||
<ItemContainer>
|
||||
<Grid Padding="12,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<fic:FluentIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{Binding Level, Converter={StaticResource LogLevelToColorConverter}}"
|
||||
Icon="{Binding Level, Converter={StaticResource LogLevelToSymbolConverter}}"
|
||||
IconSize="Size20"
|
||||
IconVariant="Filled" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="Consolas"
|
||||
FontSize="11"
|
||||
Foreground="{StaticResource TextFillColorSecondaryBrush}">
|
||||
<Run Text="[" />
|
||||
<Run Text="{Binding Timestamp}" />
|
||||
<Run Text="]" />
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Message}"
|
||||
TextTrimming="WordEllipsis"
|
||||
TextWrapping="NoWrap" />
|
||||
</Grid>
|
||||
</ItemContainer>
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Toolbar -->
|
||||
<Border
|
||||
Grid.Row="0"
|
||||
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<StackPanel Margin="8,4" Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="ClearButton"
|
||||
Margin="0,0,8,0"
|
||||
Click="ClearButton_Click"
|
||||
Content="Clear" />
|
||||
<CheckBox
|
||||
x:Name="AutoScrollCheckBox"
|
||||
Margin="0,0,8,0"
|
||||
Content="Auto Scroll"
|
||||
IsChecked="True" />
|
||||
<CheckBox
|
||||
x:Name="ShowStackTraceCheckBox"
|
||||
Margin="0,0,8,0"
|
||||
Checked="ShowStackTraceCheckBox_Checked"
|
||||
Content="Stack Trace"
|
||||
Unchecked="ShowStackTraceCheckBox_Unchecked" />
|
||||
|
||||
<!-- Log level filters -->
|
||||
<TextBlock
|
||||
Margin="16,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="Show:" />
|
||||
<CheckBox
|
||||
x:Name="ShowInfoCheckBox"
|
||||
Margin="0,0,4,0"
|
||||
Content="Info"
|
||||
IsChecked="True" />
|
||||
<CheckBox
|
||||
x:Name="ShowWarningCheckBox"
|
||||
Margin="0,0,4,0"
|
||||
Content="Warning"
|
||||
IsChecked="True" />
|
||||
<CheckBox
|
||||
x:Name="ShowErrorCheckBox"
|
||||
Margin="0,0,4,0"
|
||||
Content="Error"
|
||||
IsChecked="True" />
|
||||
<CheckBox
|
||||
x:Name="ShowDebugCheckBox"
|
||||
Margin="0,0,4,0"
|
||||
Content="Debug"
|
||||
IsChecked="True" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="0.75*" MaxWidth="1000" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Log display -->
|
||||
<ScrollView
|
||||
x:Name="LogScrollView"
|
||||
Grid.Column="0"
|
||||
HorizontalScrollBarVisibility="Hidden"
|
||||
HorizontalScrollMode="Disabled"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
VerticalScrollMode="Auto"
|
||||
ZoomMode="Disabled">
|
||||
<ItemsView
|
||||
x:Name="LogItemsView"
|
||||
Padding="4"
|
||||
ItemTemplate="{StaticResource LogItemTemplate}"
|
||||
SelectionChanged="LogItemsView_SelectionChanged" />
|
||||
</ScrollView>
|
||||
|
||||
<ScrollView
|
||||
Grid.Column="1"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="1,0,0,0"
|
||||
HorizontalScrollMode="Disabled">
|
||||
<StackPanel
|
||||
Padding="12"
|
||||
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||
Spacing="8">
|
||||
<TextBlock Style="{StaticResource BodyLargeStrongTextBlockStyle}" Text="Selected Log Details" />
|
||||
<TextBlock
|
||||
Margin="8,0,0,0"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Message:" />
|
||||
<TextBlock
|
||||
x:Name="SelectedLogMessageTextBlock"
|
||||
Margin="16,0,0,0"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Margin="8,0,0,0"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Stack Trace:" />
|
||||
<TextBlock
|
||||
x:Name="SelectedLogStackTraceTextBlock"
|
||||
Margin="16,0,0,0"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</ScrollView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
180
src/Editor/Ghost.Editor/Views/Controls/LogViewer.xaml.cs
Normal file
180
src/Editor/Ghost.Editor/Views/Controls/LogViewer.xaml.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using FluentIcons.Common;
|
||||
using Ghost.Core;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Ghost.Editor.Views.Controls;
|
||||
|
||||
public sealed partial class LogViewer : UserControl
|
||||
{
|
||||
private readonly ObservableCollection<LogMessage> _filteredLogs = [];
|
||||
|
||||
public LogViewer()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
LogItemsView.ItemsSource = _filteredLogs;
|
||||
|
||||
Logger.Impl.OnLogAdded += OnLogAdded;
|
||||
Logger.Impl.OnLogsCleared += OnLogCleared;
|
||||
|
||||
// Subscribe to filter changes
|
||||
ShowInfoCheckBox.Checked += OnFilterChanged;
|
||||
ShowInfoCheckBox.Unchecked += OnFilterChanged;
|
||||
ShowWarningCheckBox.Checked += OnFilterChanged;
|
||||
ShowWarningCheckBox.Unchecked += OnFilterChanged;
|
||||
ShowErrorCheckBox.Checked += OnFilterChanged;
|
||||
ShowErrorCheckBox.Unchecked += OnFilterChanged;
|
||||
ShowDebugCheckBox.Checked += OnFilterChanged;
|
||||
ShowDebugCheckBox.Unchecked += OnFilterChanged;
|
||||
|
||||
// Load existing logs
|
||||
RefreshLogs();
|
||||
}
|
||||
|
||||
private void OnLogAdded(LogMessage message)
|
||||
{
|
||||
if (ShouldShowLogItem(message))
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
_filteredLogs.Add(message);
|
||||
if (AutoScrollCheckBox.IsChecked == true)
|
||||
{
|
||||
LogScrollView.UpdateLayout();
|
||||
LogScrollView.ScrollTo(0.0, LogScrollView.ScrollableHeight);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLogCleared()
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(_filteredLogs.Clear);
|
||||
}
|
||||
|
||||
private void OnFilterChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RefreshLogs();
|
||||
}
|
||||
|
||||
private bool ShouldShowLogItem(LogMessage message)
|
||||
{
|
||||
return message.Level switch
|
||||
{
|
||||
LogLevel.Info => ShowInfoCheckBox.IsChecked == true,
|
||||
LogLevel.Warning => ShowWarningCheckBox.IsChecked == true,
|
||||
LogLevel.Error => ShowErrorCheckBox.IsChecked == true,
|
||||
LogLevel.Debug => ShowDebugCheckBox.IsChecked == true,
|
||||
_ => true
|
||||
};
|
||||
}
|
||||
|
||||
private void RefreshLogs()
|
||||
{
|
||||
_filteredLogs.Clear();
|
||||
Logger.Info("Message");
|
||||
|
||||
foreach (var log in Logger.Logs)
|
||||
{
|
||||
if (ShouldShowLogItem(log))
|
||||
{
|
||||
_filteredLogs.Add(log);
|
||||
}
|
||||
}
|
||||
|
||||
if (AutoScrollCheckBox.IsChecked == true)
|
||||
{
|
||||
LogScrollView.UpdateLayout();
|
||||
LogScrollView.ScrollTo(0.0, LogScrollView.ScrollableHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Logger.Impl.Clear();
|
||||
}
|
||||
|
||||
private void ShowStackTraceCheckBox_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Logger.Impl.CaptureStackTrace = true;
|
||||
}
|
||||
|
||||
private void ShowStackTraceCheckBox_Unchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Logger.Impl.CaptureStackTrace = false;
|
||||
}
|
||||
|
||||
private void LogItemsView_SelectionChanged(ItemsView sender, ItemsViewSelectionChangedEventArgs args)
|
||||
{
|
||||
if (sender.SelectedItem is LogMessage selectedLog)
|
||||
{
|
||||
SelectedLogMessageTextBlock.Text = selectedLog.Message;
|
||||
SelectedLogStackTraceTextBlock.Text = selectedLog.StackTrace ?? "Stack trace not available.";
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedLogMessageTextBlock.Text = string.Empty;
|
||||
SelectedLogStackTraceTextBlock.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Converter for log level to color
|
||||
public partial class LogLevelToColorConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is LogLevel level)
|
||||
{
|
||||
Application.Current.Resources.TryGetValue("SystemFillColorAttentionBrush", out var infoBrush);
|
||||
Application.Current.Resources.TryGetValue("SystemFillColorCautionBrush", out var warningBrush);
|
||||
Application.Current.Resources.TryGetValue("SystemFillColorCriticalBrush", out var errorBrush);
|
||||
Application.Current.Resources.TryGetValue("SystemFillColorNeutralBrush", out var debugBrush);
|
||||
|
||||
return level switch
|
||||
{
|
||||
LogLevel.Info => infoBrush,
|
||||
LogLevel.Warning => warningBrush,
|
||||
LogLevel.Error => errorBrush,
|
||||
LogLevel.Debug => debugBrush,
|
||||
_ => new SolidColorBrush(Colors.Black)
|
||||
};
|
||||
}
|
||||
return new SolidColorBrush(Colors.Black);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
// Converter for log level to symbol
|
||||
public partial class LogLevelToSymbolConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is LogLevel level)
|
||||
{
|
||||
return level switch
|
||||
{
|
||||
LogLevel.Info => Icon.Info,
|
||||
LogLevel.Warning => Icon.Warning,
|
||||
LogLevel.Error => Icon.ErrorCircle,
|
||||
LogLevel.Debug => Icon.Bug,
|
||||
_ => Icon.Info
|
||||
};
|
||||
}
|
||||
return Icon.Info;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
288
src/Editor/Ghost.Editor/Views/Pages/EditPage.xaml
Normal file
288
src/Editor/Ghost.Editor/Views/Pages/EditPage.xaml
Normal file
@@ -0,0 +1,288 @@
|
||||
<Page
|
||||
x:Class="Ghost.Editor.Views.Pages.EditPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Ghost.Editor.Views.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Background="{ThemeResource LayerFillColorDefaultBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Toolbar -->
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Padding="8,0"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource ControlElevationBorderBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Orientation="Horizontal">
|
||||
<ComboBox
|
||||
Width="200"
|
||||
VerticalAlignment="Center"
|
||||
SelectedIndex="0">
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
<TextBlock Text="Selection Mode" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
<TextBlock Text="Placement Mode" />
|
||||
</StackPanel>
|
||||
</ComboBox>
|
||||
|
||||
<Border Height="12" Style="{StaticResource VerticalDivider}" />
|
||||
|
||||
<MenuBar>
|
||||
<MenuBarItem Title="File">
|
||||
<MenuFlyoutItem Text="New" />
|
||||
<MenuFlyoutItem Text="Open..." />
|
||||
<MenuFlyoutItem Text="Save" />
|
||||
<MenuFlyoutItem Text="Exit" />
|
||||
</MenuBarItem>
|
||||
|
||||
<MenuBarItem Title="Edit">
|
||||
<MenuFlyoutItem Text="Undo" />
|
||||
<MenuFlyoutItem Text="Cut" />
|
||||
<MenuFlyoutItem Text="Copy" />
|
||||
<MenuFlyoutItem Text="Paste" />
|
||||
</MenuBarItem>
|
||||
|
||||
<MenuBarItem Title="Help">
|
||||
<MenuFlyoutItem Text="About" />
|
||||
</MenuBarItem>
|
||||
</MenuBar>
|
||||
</StackPanel>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.25*" MaxWidth="350" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="0.25*" MaxWidth="350" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Hierarchy -->
|
||||
<Grid
|
||||
Grid.Column="0"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,1,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Padding="8,2,4,4"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Style="{StaticResource BodyLargeStrongTextBlockStyle}"
|
||||
Text="Hierarchy" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon Glyph="" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<Grid Margin="0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<FontIcon
|
||||
Grid.Column="0"
|
||||
Margin="0,0,4,0"
|
||||
FontSize="{StaticResource ToolbarFontIconFontSize}"
|
||||
Glyph="" />
|
||||
<TextBox Grid.Column="1" PlaceholderText="Sreach item..." />
|
||||
</Grid>
|
||||
|
||||
<Border Margin="-8,8,-4,-4" Style="{StaticResource HorizontalStrongDivider}" />
|
||||
</StackPanel>
|
||||
|
||||
<ListView Grid.Row="1" Padding="4,2,0,2">
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
</ListView>
|
||||
</Grid>
|
||||
|
||||
<!-- Scene and Content -->
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="0.3*" MaxHeight="350" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Scene Toolbar -->
|
||||
<StackPanel
|
||||
Padding="2"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Orientation="Horizontal">
|
||||
<Button Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
<Button Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
<Button Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Scene -->
|
||||
<Border
|
||||
Grid.Row="1"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<Image
|
||||
VerticalAlignment="Center"
|
||||
Source="C:/Users/Misaki/OneDrive/Pictures/Screenshots/Screenshot 2023-11-28 000914.png"
|
||||
Stretch="UniformToFill" />
|
||||
</Border>
|
||||
|
||||
|
||||
<!-- Content Brower -->
|
||||
<Border
|
||||
Grid.Row="2"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CircleElevationBorderBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<SelectorBar SelectionChanged="SelectorBar_SelectionChanged">
|
||||
<SelectorBarItem IsSelected="True" Text="Project" />
|
||||
<SelectorBarItem Text="Console" />
|
||||
<SelectorBarItem Text="Log" />
|
||||
</SelectorBar>
|
||||
</Border>
|
||||
|
||||
<ContentPresenter x:Name="ContentBrowserPresenter" Grid.Row="3" />
|
||||
</Grid>
|
||||
|
||||
<!-- Inspector -->
|
||||
<Grid
|
||||
Grid.Column="2"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="1,0,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Inspector Header -->
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
Padding="12,12,8,12"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource ControlElevationBorderBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<FontIcon
|
||||
Grid.Column="0"
|
||||
FontSize="18"
|
||||
Glyph="" />
|
||||
<TextBox
|
||||
Grid.Column="1"
|
||||
FontSize="14"
|
||||
Text="Name" />
|
||||
<DropDownButton
|
||||
Grid.Column="2"
|
||||
Padding="2"
|
||||
Style="{ThemeResource ToolbarButton}">
|
||||
<DropDownButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuFlyoutItem Text="Send" />
|
||||
<MenuFlyoutItem Text="Reply" />
|
||||
<MenuFlyoutItem Text="Reply All" />
|
||||
</MenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
<FontIcon FontSize="12" Glyph="" />
|
||||
</DropDownButton>
|
||||
</Grid>
|
||||
|
||||
<!-- Content -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" MaxHeight="150" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" Padding="8,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Components" />
|
||||
<Button Grid.Column="1" Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
<Button Grid.Column="2" Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<AutoSuggestBox
|
||||
Grid.Row="1"
|
||||
Margin="8,0"
|
||||
PlaceholderText="Search components..." />
|
||||
|
||||
<!-- Components List -->
|
||||
<ListView
|
||||
Grid.Row="2"
|
||||
Padding="4,2,0,2"
|
||||
SelectionMode="Extended">
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
</ListView>
|
||||
|
||||
<!-- Component Properties for Selected Component -->
|
||||
<ScrollView
|
||||
Grid.Row="3"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,1,0,0">
|
||||
<ItemsRepeater />
|
||||
</ScrollView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Page>
|
||||
37
src/Editor/Ghost.Editor/Views/Pages/EditPage.xaml.cs
Normal file
37
src/Editor/Ghost.Editor/Views/Pages/EditPage.xaml.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Ghost.Editor.Views.Controls;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Ghost.Editor.Views.Pages;
|
||||
|
||||
public sealed partial class EditPage : Page
|
||||
{
|
||||
private readonly ContentBrowser _contentBrowser;
|
||||
private readonly LogViewer _logViewer;
|
||||
|
||||
public EditPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_contentBrowser = new ContentBrowser();
|
||||
_logViewer = new LogViewer();
|
||||
|
||||
ContentBrowserPresenter.Content = _contentBrowser;
|
||||
}
|
||||
|
||||
private void SelectorBar_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)
|
||||
{
|
||||
var selectedItem = sender.SelectedItem;
|
||||
var currentSelectedIndex = sender.Items.IndexOf(selectedItem);
|
||||
switch (currentSelectedIndex)
|
||||
{
|
||||
case 0:
|
||||
ContentBrowserPresenter.Content = _contentBrowser;
|
||||
break;
|
||||
case 2:
|
||||
ContentBrowserPresenter.Content = _logViewer;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,366 +59,20 @@
|
||||
|
||||
<Border Height="12" Style="{StaticResource VerticalDivider}" />
|
||||
|
||||
<SelectorBar>
|
||||
<SelectorBarItem Text="Edit" />
|
||||
<SelectorBarItem Text="Analysis" />
|
||||
<SelectorBarItem Text="Build" />
|
||||
<SelectorBar SelectionChanged="SelectorBar_SelectionChanged">
|
||||
<SelectorBarItem
|
||||
x:Name="EditSelectorItem"
|
||||
IsSelected="True"
|
||||
Text="Edit" />
|
||||
<SelectorBarItem x:Name="AnalysisSelectorItem" Text="Analysis" />
|
||||
<SelectorBarItem x:Name="BuildSelectorItem" Text="Build" />
|
||||
</SelectorBar>
|
||||
</StackPanel>
|
||||
|
||||
<!--<Frame
|
||||
<Frame
|
||||
x:Name="ContentFrame"
|
||||
Grid.Row="2"
|
||||
IsNavigationStackEnabled="False" />-->
|
||||
<!-- Edit View -->
|
||||
<Grid Grid.Row="1" Background="{ThemeResource LayerFillColorDefaultBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Toolbar -->
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Padding="8,0"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
Orientation="Horizontal">
|
||||
<ComboBox
|
||||
Width="200"
|
||||
VerticalAlignment="Center"
|
||||
SelectedIndex="0">
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
<TextBlock Text="Selection Mode" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
<TextBlock Text="Placement Mode" />
|
||||
</StackPanel>
|
||||
</ComboBox>
|
||||
|
||||
<Border Height="12" Style="{StaticResource VerticalDivider}" />
|
||||
|
||||
<MenuBar>
|
||||
<MenuBarItem Title="File">
|
||||
<MenuFlyoutItem Text="New" />
|
||||
<MenuFlyoutItem Text="Open..." />
|
||||
<MenuFlyoutItem Text="Save" />
|
||||
<MenuFlyoutItem Text="Exit" />
|
||||
</MenuBarItem>
|
||||
|
||||
<MenuBarItem Title="Edit">
|
||||
<MenuFlyoutItem Text="Undo" />
|
||||
<MenuFlyoutItem Text="Cut" />
|
||||
<MenuFlyoutItem Text="Copy" />
|
||||
<MenuFlyoutItem Text="Paste" />
|
||||
</MenuBarItem>
|
||||
|
||||
<MenuBarItem Title="Help">
|
||||
<MenuFlyoutItem Text="About" />
|
||||
</MenuBarItem>
|
||||
</MenuBar>
|
||||
</StackPanel>
|
||||
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,1,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.25*" MaxWidth="350" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="0.25*" MaxWidth="350" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Hierarchy -->
|
||||
<Grid
|
||||
Grid.Column="0"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,1,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Padding="8,2,4,4"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Style="{StaticResource BodyLargeStrongTextBlockStyle}"
|
||||
Text="Hierarchy" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon Glyph="" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<Grid Margin="0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<FontIcon
|
||||
Grid.Column="0"
|
||||
Margin="0,0,4,0"
|
||||
FontSize="{StaticResource ToolbarFontIconFontSize}"
|
||||
Glyph="" />
|
||||
<TextBox Grid.Column="1" PlaceholderText="Sreach item..." />
|
||||
</Grid>
|
||||
|
||||
<Border Margin="-8,8,-4,-4" Style="{StaticResource HorizontalDivider}" />
|
||||
</StackPanel>
|
||||
|
||||
<ListView Grid.Row="1" Padding="4,2,0,2">
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
</ListView>
|
||||
</Grid>
|
||||
|
||||
<!-- Scene and Content -->
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="0.3*" MaxHeight="350" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Scene Toolbar -->
|
||||
<StackPanel
|
||||
Padding="2"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Orientation="Horizontal">
|
||||
<Button Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
<Button Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
<Button Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Scene -->
|
||||
<Image
|
||||
Grid.Row="1"
|
||||
VerticalAlignment="Center"
|
||||
Source="C:/Users/Misaki/OneDrive/Pictures/Screenshots/Screenshot 2023-11-28 000914.png"
|
||||
Stretch="UniformToFill" />
|
||||
|
||||
<!-- Content Brower -->
|
||||
<Border
|
||||
Grid.Row="2"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,1,0,1">
|
||||
<SelectorBar>
|
||||
<SelectorBarItem Text="Project" />
|
||||
<SelectorBarItem Text="Console" />
|
||||
<SelectorBarItem Text="Log" />
|
||||
</SelectorBar>
|
||||
</Border>
|
||||
|
||||
<!--<Frame Name="ContentBrowerFrame" Grid.Row="3" />-->
|
||||
<Grid Grid.Row="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.15*" MaxWidth="250" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,1,0">
|
||||
<ListView>
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
<ListViewItem Content="Test" />
|
||||
</ListView>
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
Padding="8,4"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel
|
||||
Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Spacing="4">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
<AutoSuggestBox Width="300" PlaceholderText="Search asset..." />
|
||||
<DropDownButton Padding="2" Style="{ThemeResource ToolbarButton}">
|
||||
<DropDownButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuFlyoutItem Text="Send" />
|
||||
<MenuFlyoutItem Text="Reply" />
|
||||
<MenuFlyoutItem Text="Reply All" />
|
||||
</MenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
<FontIcon FontSize="12" Glyph="" />
|
||||
</DropDownButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<!-- Inspector -->
|
||||
<Grid
|
||||
Grid.Column="2"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="1,0,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Inspector Header -->
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
Padding="12,12,8,12"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<FontIcon
|
||||
Grid.Column="0"
|
||||
FontSize="18"
|
||||
Glyph="" />
|
||||
<TextBox
|
||||
Grid.Column="1"
|
||||
FontSize="14"
|
||||
Text="Name" />
|
||||
<DropDownButton
|
||||
Grid.Column="2"
|
||||
Padding="2"
|
||||
Style="{ThemeResource ToolbarButton}">
|
||||
<DropDownButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuFlyoutItem Text="Send" />
|
||||
<MenuFlyoutItem Text="Reply" />
|
||||
<MenuFlyoutItem Text="Reply All" />
|
||||
</MenuFlyout>
|
||||
</DropDownButton.Flyout>
|
||||
<FontIcon FontSize="12" Glyph="" />
|
||||
</DropDownButton>
|
||||
</Grid>
|
||||
|
||||
<!-- Content -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" MaxHeight="150" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" Padding="8,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Components" />
|
||||
<Button Grid.Column="1" Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
<Button Grid.Column="2" Style="{ThemeResource ToolbarButton}">
|
||||
<FontIcon FontSize="{StaticResource ToolbarFontIconFontSize}" Glyph="" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<AutoSuggestBox
|
||||
Grid.Row="1"
|
||||
Margin="8,0"
|
||||
PlaceholderText="Search components..." />
|
||||
|
||||
<!-- Components List -->
|
||||
<ListView
|
||||
Grid.Row="2"
|
||||
Padding="4,2,0,2"
|
||||
SelectionMode="Extended">
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
<TextBlock Text="Test" />
|
||||
</ListView>
|
||||
|
||||
<!-- Component Properties for Selected Component -->
|
||||
<ScrollView
|
||||
Grid.Row="3"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,1,0,0">
|
||||
<ItemsRepeater />
|
||||
</ScrollView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
Grid.Row="1"
|
||||
IsNavigationStackEnabled="False" />
|
||||
|
||||
<!-- Status Bar -->
|
||||
<Grid
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
using Ghost.Editor.ViewModels.Windows;
|
||||
using Ghost.Editor.Views.Pages;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using WinUIEx;
|
||||
|
||||
namespace Ghost.Editor.Views.Windows;
|
||||
|
||||
internal sealed partial class EngineEditorWindow : WindowEx
|
||||
{
|
||||
private int _previousSelectedIndex = 0;
|
||||
|
||||
public EngineEditorViewModel ViewModel
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public EngineEditorWindow()
|
||||
{
|
||||
ViewModel = App.GetService<EngineEditorViewModel>();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/icon.ico"));
|
||||
@@ -13,5 +26,28 @@ internal sealed partial class EngineEditorWindow : WindowEx
|
||||
Title = "Ghost Engine";
|
||||
|
||||
SetTitleBar(TitleBar);
|
||||
|
||||
ContentFrame.Navigate(typeof(EditPage));
|
||||
}
|
||||
|
||||
private void SelectorBar_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)
|
||||
{
|
||||
var selectedItem = sender.SelectedItem;
|
||||
var currentSelectedIndex = sender.Items.IndexOf(selectedItem);
|
||||
if (currentSelectedIndex == _previousSelectedIndex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pageType = currentSelectedIndex switch
|
||||
{
|
||||
0 => typeof(EditPage),
|
||||
_ => typeof(EditPage),
|
||||
};
|
||||
|
||||
var slideNavigationTransitionEffect = currentSelectedIndex - _previousSelectedIndex > 0 ? SlideNavigationTransitionEffect.FromRight : SlideNavigationTransitionEffect.FromLeft;
|
||||
|
||||
ContentFrame.Navigate(pageType, null, new SlideNavigationTransitionInfo() { Effect = slideNavigationTransitionEffect });
|
||||
_previousSelectedIndex = currentSelectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user