diff --git a/src/SharpFM/Editors/ScriptTextEditor.cs b/src/SharpFM/Editors/ScriptTextEditor.cs new file mode 100644 index 0000000..dbfe71a --- /dev/null +++ b/src/SharpFM/Editors/ScriptTextEditor.cs @@ -0,0 +1,68 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Avalonia; +using Avalonia.Controls; +using AvaloniaEdit; +using AvaloniaEdit.TextMate; +using SharpFM.Scripting; +using SharpFM.Scripting.Editor; +using SharpFM.ViewModels; +using TextMateSharp.Grammars; + +namespace SharpFM.Editors; + +/// +/// A specialized for script clips. Owns its +/// TextMate installation and so it +/// can be dropped into a DataTemplate without any parent wiring — +/// each instance self-installs on construction and tears down on detach. +/// DataContext is expected to be a . +/// +[ExcludeFromCodeCoverage] +public class ScriptTextEditor : TextEditor +{ + // Avalonia 12 matches styles by exact type. Without this, a subclass of + // TextEditor gets no control template and renders blank — the editor's + // TextArea/TextView visual tree is never built. + protected override Type StyleKeyOverride => typeof(TextEditor); + + private readonly TextMate.Installation _textMate; + private readonly ScriptEditorController _controller; + + public ScriptTextEditor() + { + var registry = new RegistryOptions((ThemeName)(int)ThemeName.DarkPlus); + var fmScriptRegistry = new FmScriptRegistryOptions(registry); + _textMate = this.InstallTextMate(fmScriptRegistry); + _textMate.SetGrammar(FmScriptRegistryOptions.ScopeName); + + _controller = new ScriptEditorController(this); + _controller.StatusMessageRaised += OnStatusMessageRaised; + } + + protected override void OnDataContextChanged(EventArgs e) + { + base.OnDataContextChanged(e); + + if (DataContext is not ScriptClipEditor clipEditor) return; + + Document = clipEditor.Document; + _controller.AttachClipEditor(clipEditor); + } + + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnDetachedFromVisualTree(e); + + _controller.StatusMessageRaised -= OnStatusMessageRaised; + _controller.Dispose(); + _textMate.Dispose(); + } + + private void OnStatusMessageRaised(object? sender, StatusMessageEventArgs e) + { + var window = TopLevel.GetTopLevel(this) as Window; + if (window?.DataContext is MainWindowViewModel vm) + vm.ShowStatusMessage(e.Message, e.IsError); + } +} diff --git a/src/SharpFM/MainWindow.axaml b/src/SharpFM/MainWindow.axaml index e80e582..346e6da 100644 --- a/src/SharpFM/MainWindow.axaml +++ b/src/SharpFM/MainWindow.axaml @@ -6,6 +6,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="using:SharpFM.ViewModels" + xmlns:editors="using:SharpFM.Editors" xmlns:schema="using:SharpFM.Schema.Editor" Icon="/Assets/noun-sharp-teeth-monster-4226695.small.png" Title="SharpFM" @@ -206,33 +207,40 @@ - + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/src/SharpFM/MainWindow.axaml.cs b/src/SharpFM/MainWindow.axaml.cs index 0927958..4e3002f 100644 --- a/src/SharpFM/MainWindow.axaml.cs +++ b/src/SharpFM/MainWindow.axaml.cs @@ -1,29 +1,21 @@ using System; -using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using Avalonia; using Avalonia.Controls; using Avalonia.Input; -using AvaloniaEdit; -using AvaloniaEdit.TextMate; using SharpFM.Diagnostics; using SharpFM.Plugin; using SharpFM.Plugin.UI; using SharpFM.PluginManager; -using SharpFM.Scripting; using SharpFM.Services; using SharpFM.ViewModels; -using TextMateSharp.Grammars; namespace SharpFM; [ExcludeFromCodeCoverage] public partial class MainWindow : Window { - private readonly RegistryOptions _registryOptions; - private ScriptEditorController? _scriptController; - private TextMate.Installation? _scriptTextMateInstallation; private PluginService? _pluginService; private PluginUIHost? _pluginHost; private PluginConfigService? _pluginConfigService; @@ -32,19 +24,6 @@ public MainWindow() { InitializeComponent(); - _registryOptions = new RegistryOptions((ThemeName)(int)ThemeName.DarkPlus); - - // Script editor - var scriptEditor = this.FindControl("scriptEditor"); - if (scriptEditor != null) - { - var fmScriptRegistry = new FmScriptRegistryOptions(_registryOptions); - _scriptTextMateInstallation = scriptEditor.InstallTextMate(fmScriptRegistry); - _scriptTextMateInstallation.SetGrammar(FmScriptRegistryOptions.ScopeName); - _scriptController = new ScriptEditorController(scriptEditor); - _scriptController.StatusMessageRaised += OnScriptControllerStatusMessage; - } - // "Manage Plugins..." menu item var managePlugins = this.FindControl("managePluginsMenuItem"); if (managePlugins != null) @@ -71,18 +50,11 @@ private void OnDataContextChanged(object? sender, EventArgs e) if (DataContext is not MainWindowViewModel vm) return; BuildPluginMenuItems(vm); - vm.PropertyChanged += OnViewModelPropertyChanged; if (vm.PluginUI is { } pluginUI) pluginUI.PropertyChanged += OnPluginUIPropertyChanged; } - private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(MainWindowViewModel.SelectedClip)) - AttachScriptClipEditorIfApplicable(); - } - private void OnPluginUIPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(PluginUIHost.IsVisible)) @@ -91,22 +63,6 @@ private void OnPluginUIPropertyChanged(object? sender, PropertyChangedEventArgs UpdatePluginPanelContent(); } - private void OnScriptControllerStatusMessage(object? sender, SharpFM.Scripting.Editor.StatusMessageEventArgs e) - { - if (DataContext is MainWindowViewModel vm) - vm.ShowStatusMessage(e.Message, e.IsError); - } - - private void AttachScriptClipEditorIfApplicable() - { - if (_scriptController == null) return; - if (DataContext is not MainWindowViewModel vm) return; - if (vm.SelectedClip?.Editor is SharpFM.Editors.ScriptClipEditor clipEditor) - { - _scriptController.AttachClipEditor(clipEditor); - } - } - private void BuildPluginMenuItems(MainWindowViewModel vm) { var pluginsMenu = this.FindControl("pluginsMenu"); @@ -238,11 +194,4 @@ private void ShowPluginManager() window.Configure(_pluginService, _pluginHost, vm, _pluginConfigService); window.ShowDialog(this); } - - protected override void OnClosed(EventArgs e) - { - base.OnClosed(e); - _scriptController?.Dispose(); - _scriptTextMateInstallation?.Dispose(); - } }