From 963b18aa5ce409cc795fbcbc8d5b0505bb2845ac Mon Sep 17 00:00:00 2001 From: Neil Brommer Date: Fri, 28 Jul 2023 13:33:40 -0700 Subject: [PATCH] Convert to a document based application --- Cauldron.Macos/AppDelegate.cs | 7 -- Cauldron.Macos/AppDelegate.designer.cs | 3 - Cauldron.Macos/CSharpScriptDocument.cs | 67 +++++++++++++++++++ Cauldron.Macos/Info.plist | 65 ++++++++++++++---- Cauldron.Macos/Main.storyboard | 17 +---- Cauldron.Macos/MainWindow.cs | 29 +++++--- Cauldron.Macos/ScriptRunner.cs | 2 - Cauldron.Macos/SourceWriter/SourceTextView.cs | 10 ++- 8 files changed, 151 insertions(+), 49 deletions(-) create mode 100644 Cauldron.Macos/CSharpScriptDocument.cs diff --git a/Cauldron.Macos/AppDelegate.cs b/Cauldron.Macos/AppDelegate.cs index f88e289..26e7747 100644 --- a/Cauldron.Macos/AppDelegate.cs +++ b/Cauldron.Macos/AppDelegate.cs @@ -27,13 +27,6 @@ public partial class AppDelegate : NSApplicationDelegate as MainWindow); } - partial void NewTabMenuItemClicked(AppKit.NSMenuItem sender) - { - (NSApplication.SharedApplication.KeyWindow.WindowController - as MainWindow) - .CreateNewTab(); - } - [Action("validateMenuItem:")] public bool ValidateMenuItem(AppKit.NSMenuItem sender) { diff --git a/Cauldron.Macos/AppDelegate.designer.cs b/Cauldron.Macos/AppDelegate.designer.cs index 3d3ef68..c7f493b 100644 --- a/Cauldron.Macos/AppDelegate.designer.cs +++ b/Cauldron.Macos/AppDelegate.designer.cs @@ -11,9 +11,6 @@ namespace Cauldron.Macos { partial class AppDelegate { - [Action ("NewTabMenuItemClicked:")] - partial void NewTabMenuItemClicked (AppKit.NSMenuItem sender); - [Action ("RunScriptMenuItemClicked:")] partial void RunScriptMenuItemClicked (AppKit.NSMenuItem sender); diff --git a/Cauldron.Macos/CSharpScriptDocument.cs b/Cauldron.Macos/CSharpScriptDocument.cs new file mode 100644 index 0000000..38c19a6 --- /dev/null +++ b/Cauldron.Macos/CSharpScriptDocument.cs @@ -0,0 +1,67 @@ +using System; +using AppKit; +using Foundation; + +namespace Cauldron.Macos; + +[Register("CSharpScriptDocument")] +public class CSharpScriptDocument : NSDocument +{ + public NSString _scriptText = new(""); + [Export("ScriptText")] + public NSString ScriptText + { + get => this._scriptText; + set + { + this._scriptText = value; + if (this.MainWindow != null) + this.MainWindow.ContentViewController.RepresentedObject = value; + + this.MainWindow?.SetDocumentEdited(this.IsDocumentEdited); + } + } + public NSString SavedScriptText { get; set; } + public MainWindow MainWindow { get; set; } + + public CSharpScriptDocument() : base() { } + public CSharpScriptDocument(ObjCRuntime.NativeHandle handle) : base(handle) { } + + public override void MakeWindowControllers() + { + NSStoryboard storyboard = NSStoryboard.FromName("Main", null); + MainWindow windowController = (MainWindow)storyboard + .InstantiateControllerWithIdentifier("MainWindowController"); + windowController.ContentViewController.RepresentedObject = this.ScriptText; + + windowController.ScriptEditorTextBox.Value = this.ScriptText; + windowController.ScriptEditorTextBox.Formatter.Reformat(); + windowController.WindowTitleForDocumentDisplayName(this.DisplayName); + windowController.SynchronizeWindowTitleWithDocumentName(); + windowController.Window.Subtitle = this.FileUrl?.FilePathUrl.Path ?? ""; + windowController.SetDocumentEdited(this.IsDocumentEdited); + + this.AddWindowController(windowController); + } + + public override bool IsDocumentEdited { get => this.ScriptText != this.SavedScriptText; } + + public override NSData GetAsData(string typeName, out NSError outError) + { + outError = null; + return NSData.FromString(this.ScriptText); + } + + public override bool ReadFromData(NSData data, string typeName, out NSError outError) + { + outError = null; + this.SavedScriptText = this.ScriptText = new NSString(data, NSStringEncoding.UTF8); + return true; + } + + [Export("autosavesInPlace")] + public static bool AutosaveInPlace() + { + return false; + } +} diff --git a/Cauldron.Macos/Info.plist b/Cauldron.Macos/Info.plist index a42dc71..119be4f 100644 --- a/Cauldron.Macos/Info.plist +++ b/Cauldron.Macos/Info.plist @@ -2,30 +2,71 @@ - CFBundleName - Cauldron + CFBundleDevelopmentRegion + en + CFBundleDocumentTypes + + + CFBundleTypeIconFile + + CFBundleTypeName + C# Script + CFBundleTypeRole + Editor + LSHandlerRank + Default + LSItemContentTypes + + com.neilbrommer.cauldron-CsScript + + NSDocumentClass + CSharpScriptDocument + + CFBundleIdentifier com.neilbrommer.cauldron + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Cauldron + CFBundlePackageType + APPL CFBundleShortVersionString 1.0 + CFBundleSignature + ???? CFBundleVersion 1 LSMinimumSystemVersion 13.0 - CFBundleDevelopmentRegion - en - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - APPL - CFBundleSignature - ???? NSHumanReadableCopyright ${AuthorCopyright:HtmlEncode} - NSPrincipalClass - NSApplication NSMainStoryboardFile Main + NSPrincipalClass + NSApplication + UTExportedTypeDeclarations + + + UTTypeConformsTo + + public.script + + UTTypeDescription + C# Script + UTTypeIcons + + UTTypeIdentifier + com.neilbrommer.cauldron-CsScript + UTTypeTagSpecification + + public.filename-extension + + csx + + + + XSAppIconAssets Assets.xcassets/AppIcon.appiconset diff --git a/Cauldron.Macos/Main.storyboard b/Cauldron.Macos/Main.storyboard index d54b2da..9bd0430 100644 --- a/Cauldron.Macos/Main.storyboard +++ b/Cauldron.Macos/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -67,11 +67,6 @@ - - - - - @@ -419,7 +414,7 @@ - + @@ -440,11 +435,6 @@ - - - - - @@ -473,7 +463,6 @@ - @@ -487,6 +476,7 @@ + @@ -652,7 +642,6 @@ - diff --git a/Cauldron.Macos/MainWindow.cs b/Cauldron.Macos/MainWindow.cs index 0986677..89dc665 100644 --- a/Cauldron.Macos/MainWindow.cs +++ b/Cauldron.Macos/MainWindow.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Immutable; using System.Linq; using System.Threading; -using System.Threading.Tasks; using System.Timers; using AppKit; using Cauldron.Macos.SourceWriter; @@ -14,6 +13,8 @@ namespace Cauldron.Macos; public partial class MainWindow : NSWindowController { + public CSharpScriptDocument ScriptDocument { get => (CSharpScriptDocument)this.Document; } + #region Window components private NSSplitViewController MainContentController @@ -34,7 +35,7 @@ public partial class MainWindow : NSWindowController .ContentView.DocumentView as NSOutlineView; } - private SourceTextView ScriptEditorTextBox + public SourceTextView ScriptEditorTextBox { get => (this.MainContentController .SplitViewItems[0].ViewController.View as NSScrollView) @@ -60,14 +61,21 @@ public partial class MainWindow : NSWindowController public MainWindow (ObjCRuntime.NativeHandle handle) : base (handle) { } - public override void AwakeFromNib() + public override void WindowDidLoad() { - base.AwakeFromNib(); + base.WindowDidLoad(); + + this.Document ??= new CSharpScriptDocument(); + + if (this.ScriptDocument.ScriptText == null) + this.ScriptDocument.ScriptText = new NSString(this.ScriptText); this.RunScriptToolbarButton.Activated += RunScript; SourceTextView scriptTextBox = this.ScriptEditorTextBox; scriptTextBox.OnFinishedTyping += this.BuildScript; + scriptTextBox.OnTextChanged += this.UpdateDocument; + scriptTextBox.Font = NSFont.MonospacedSystemFont(new nfloat(14), NSFontWeight.Regular); scriptTextBox.AutomaticQuoteSubstitutionEnabled = false; scriptTextBox.AutomaticDashSubstitutionEnabled = false; @@ -79,6 +87,14 @@ public partial class MainWindow : NSWindowController scriptTextBox.Formatter = new LanguageFormatter(scriptTextBox, new CSharpDescriptor()); scriptTextBox.Formatter.Reformat(); + + this.SetDocumentEdited(this.ScriptDocument.IsDocumentEdited); + } + + public void UpdateDocument(object sender, EventArgs args) + { + this.ScriptDocument.ScriptText = new NSString(this.ScriptText); + this.SetDocumentEdited(this.ScriptDocument.IsDocumentEdited); } public void BuildScript(object sender, ElapsedEventArgs args) @@ -96,11 +112,6 @@ public partial class MainWindow : NSWindowController this.ScriptCancellationTokenSource?.Cancel(); } - partial void NewTabClicked(AppKit.NSToolbarItem sender) - { - this.CreateNewTab(); - } - partial void NewTabMenuItemClicked(AppKit.NSMenuItem sender) { this.CreateNewTab(); diff --git a/Cauldron.Macos/ScriptRunner.cs b/Cauldron.Macos/ScriptRunner.cs index 64ef4fc..4bb8a73 100644 --- a/Cauldron.Macos/ScriptRunner.cs +++ b/Cauldron.Macos/ScriptRunner.cs @@ -120,8 +120,6 @@ public static class ScriptRunner + head.RenderAsString() + body.RenderAsString(); - Console.WriteLine("Contents: " + contents); - webView.LoadHtmlString(new Foundation.NSString(contents), null); } diff --git a/Cauldron.Macos/SourceWriter/SourceTextView.cs b/Cauldron.Macos/SourceWriter/SourceTextView.cs index 40f68c1..acfd397 100644 --- a/Cauldron.Macos/SourceWriter/SourceTextView.cs +++ b/Cauldron.Macos/SourceWriter/SourceTextView.cs @@ -452,6 +452,9 @@ public class SourceTextView : NSTextView /// public event ElapsedEventHandler OnFinishedTyping; + /// Triggered when the value in the textbox is changed + public event EventHandler OnTextChanged; + /// /// Look for special keys being pressed and does specific processing based on the key. /// @@ -586,11 +589,14 @@ public class SourceTextView : NSTextView } this.Formatter.Reformat(); + this.OnTextChanged.Invoke(this, null); this.InputTimoutTimer?.Stop(); this.InputTimoutTimer?.Close(); - this.InputTimoutTimer = new Timer(this.InputTimeoutInterval); - this.InputTimoutTimer.AutoReset = false; + this.InputTimoutTimer = new(this.InputTimeoutInterval) + { + AutoReset = false + }; this.InputTimoutTimer.Elapsed += this.OnFinishedTyping; this.InputTimoutTimer.Start(); }