Use a web view for output

This commit is contained in:
Neil Brommer 2023-07-21 17:20:46 -07:00
parent 1f8d7a661b
commit e887ce9507
5 changed files with 87 additions and 39 deletions

View file

@ -48,4 +48,8 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Cauldron.Core\Cauldron.Core.csproj" /> <ProjectReference Include="..\Cauldron.Core\Cauldron.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
</ItemGroup>
</Project> </Project>

View file

@ -0,0 +1,17 @@
using System.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html;
namespace Cauldron.Macos;
public static class Extensions
{
public static string RenderAsString(this IHtmlContent htmlContent)
{
using (var writer = new StringWriter())
{
htmlContent.WriteTo(writer, HtmlEncoder.Default);
return writer.ToString();
}
}
}

View file

@ -2,6 +2,7 @@
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="JKR-xj-8kh"> <document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="JKR-xj-8kh">
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/>
<plugIn identifier="com.apple.WebKit2IBPlugin" version="21701"/>
<capability name="NSView safe area layout guides" minToolsVersion="12.0"/> <capability name="NSView safe area layout guides" minToolsVersion="12.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
@ -567,37 +568,18 @@
<scene sceneID="l4o-FF-cV6"> <scene sceneID="l4o-FF-cV6">
<objects> <objects>
<viewController id="71j-pP-grU" sceneMemberID="viewController"> <viewController id="71j-pP-grU" sceneMemberID="viewController">
<scrollView key="view" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" id="DqK-nD-55b"> <wkWebView key="view" wantsLayer="YES" id="8OW-Al-ci0">
<rect key="frame" x="0.0" y="0.0" width="700" height="200"/> <rect key="frame" x="0.0" y="0.0" width="700" height="300"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" drawsBackground="NO" id="79H-al-KZe">
<rect key="frame" x="0.0" y="0.0" width="700" height="200"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView wantsLayer="YES" editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="Dvs-AF-xxf">
<rect key="frame" x="0.0" y="0.0" width="700" height="200"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="700" height="200"/>
<size key="maxSize" width="700" height="10000000"/>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
</textView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="b5v-02-4gX">
<rect key="frame" x="-100" y="-100" width="240" height="16"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</scroller> <wkWebViewConfiguration key="configuration">
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="XXI-2E-6rI"> <audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
<rect key="frame" x="684" y="0.0" width="16" height="200"/> <wkPreferences key="preferences"/>
<autoresizingMask key="autoresizingMask"/> </wkWebViewConfiguration>
</scroller> </wkWebView>
</scrollView>
</viewController> </viewController>
<customObject id="fhB-Tn-Q6J" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> <customObject id="fhB-Tn-Q6J" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="1156" y="830"/> <point key="canvasLocation" x="1156" y="882"/>
</scene> </scene>
<!--View Controller--> <!--View Controller-->
<scene sceneID="hN3-Zg-qPS"> <scene sceneID="hN3-Zg-qPS">

View file

@ -33,11 +33,10 @@ public partial class MainWindow : NSWindowController
.ContentView.DocumentView as NSTextView; .ContentView.DocumentView as NSTextView;
} }
public NSTextView ScriptOutputTextBox public WebKit.WKWebView ScriptOutputWebView
{ {
get => (this.MainContentController get => this.MainContentController
.SplitViewItems[1].ViewController.View as NSScrollView) .SplitViewItems[1].ViewController.View as WebKit.WKWebView;
.ContentView.DocumentView as NSTextView;
} }
public string ScriptText { get => this.ScriptEditorTextBox.Value; } public string ScriptText { get => this.ScriptEditorTextBox.Value; }

View file

@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Cauldron.Core; using Cauldron.Core;
namespace Cauldron.Macos; namespace Cauldron.Macos;
@ -10,16 +12,19 @@ public static class ScriptRunner
public static void RunScript(MainWindow window) public static void RunScript(MainWindow window)
{ {
window.SetScriptRunState(true); window.SetScriptRunState(true);
window.ScriptOutputTextBox.Value = "";
TagBuilder body = new("body");
window.ScriptOutputWebView.SetOutputPanelContent(body);
TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext(); TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext();
CauldronWriter writer = new(obj => CauldronWriter writer = new(obj =>
{
if (obj is string str)
{ {
window.BeginInvokeOnMainThread(() => window.BeginInvokeOnMainThread(() =>
window.ScriptOutputTextBox.Value += str + "\n"); {
} body.InnerHtml.AppendHtml(GenerateValueOutput(obj));
window.ScriptOutputWebView.SetOutputPanelContent(body);
});
return Task.CompletedTask; return Task.CompletedTask;
}); });
@ -40,11 +45,52 @@ public static class ScriptRunner
catch (Exception ex) catch (Exception ex)
{ {
window.BeginInvokeOnMainThread(() => window.BeginInvokeOnMainThread(() =>
window.ScriptOutputTextBox.Value += ex.ToString()); {
TagBuilder exTag = new("pre");
exTag.InnerHtml.Append(ex.ToString());
body.InnerHtml.AppendHtml(exTag);
window.ScriptOutputWebView.SetOutputPanelContent(body);
});
} }
}, window.ScriptCancellationTokenSource.Token) }, window.ScriptCancellationTokenSource.Token)
.ContinueWith((t) => window.SetScriptRunState(false), .ContinueWith((t) => window.SetScriptRunState(false),
uiThread); uiThread);
} }
private static TagBuilder GenerateValueOutput(object value)
{
if (value is string str)
{
TagBuilder tag = new("p");
tag.InnerHtml.Append(str);
return tag;
}
if (value.GetType().IsPrimitive)
{
TagBuilder tag = new("p");
tag.InnerHtml.Append(value.ToString());
return tag;
}
if (value is IEnumerable<object> enumberable)
{
} }
return null;
}
private static void SetOutputPanelContent(this WebKit.WKWebView webView,
TagBuilder body)
{
TagBuilder head = new("head");
string contents = "<!DOCTYPE html>"
+ head.RenderAsString()
+ body.RenderAsString();
Console.WriteLine("Contents: " + contents);
webView.LoadHtmlString(new Foundation.NSString(contents), null);
}
}