Add a popover with a list of diagnostics to the diagnostics toolbar buttons
This commit is contained in:
parent
92695b8361
commit
7610ffaf38
|
@ -44,6 +44,9 @@
|
|||
<Compile Update="AppDelegate.designer.cs">
|
||||
<DependentUpon>AppDelegate.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="DiagnosticsPopoverController.designer.cs">
|
||||
<DependentUpon>DiagnosticsPopoverController.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Cauldron.Core\Cauldron.Core.csproj" />
|
||||
|
@ -56,10 +59,12 @@
|
|||
<None Remove="SourceWriter\" />
|
||||
<None Remove="SourceWriter\LanguageFormats\" />
|
||||
<None Remove="ScriptOutput.css" />
|
||||
<None Remove="SourceList\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="SourceWriter\" />
|
||||
<Folder Include="SourceWriter\LanguageFormats\" />
|
||||
<Folder Include="SourceList\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="ScriptOutput.css" />
|
||||
|
|
69
Cauldron.Macos/DiagnosticsPopoverController.cs
Normal file
69
Cauldron.Macos/DiagnosticsPopoverController.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
using AppKit;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Cauldron.Macos.SourceList;
|
||||
using Foundation;
|
||||
|
||||
namespace Cauldron.Macos
|
||||
{
|
||||
public partial class DiagnosticsPopoverController : NSViewController
|
||||
{
|
||||
public DiagnosticSeverity Severity { get; set; }
|
||||
|
||||
public DiagnosticsPopoverController (ObjCRuntime.NativeHandle handle) : base (handle) { }
|
||||
|
||||
public override void ViewWillAppear()
|
||||
{
|
||||
base.ViewWillAppear();
|
||||
|
||||
// Build the list of diagnostics info
|
||||
|
||||
MainWindow window = NSApplication.SharedApplication.KeyWindow.WindowController
|
||||
as MainWindow;
|
||||
|
||||
ImmutableArray<Diagnostic> diagnostics = window.Diagnostics;
|
||||
|
||||
this.DiagnosticsOutlineView.Initialize();
|
||||
|
||||
SourceListItem errors = new("Errors")
|
||||
{
|
||||
IsHeader = true
|
||||
};
|
||||
SourceListItem warnings = new("Warnings")
|
||||
{
|
||||
IsHeader = true
|
||||
};
|
||||
SourceListItem infos = new("Information")
|
||||
{
|
||||
IsHeader = true
|
||||
};
|
||||
|
||||
foreach (var diagnostic in diagnostics)
|
||||
{
|
||||
SourceListItem item = new($"{diagnostic.Id} {diagnostic.GetMessage()}\n{diagnostic.Location}", "",
|
||||
() =>
|
||||
{
|
||||
window.ScriptEditorTextBox.SetSelectedRange(
|
||||
new NSRange(diagnostic.Location.SourceSpan.Start, diagnostic.Location.SourceSpan.End));
|
||||
this.DismissController(this);
|
||||
});
|
||||
|
||||
if (diagnostic.Severity == DiagnosticSeverity.Error)
|
||||
errors.AddItem(item);
|
||||
else if (diagnostic.Severity == DiagnosticSeverity.Warning)
|
||||
warnings.AddItem(item);
|
||||
else if (diagnostic.Severity == DiagnosticSeverity.Info)
|
||||
infos.AddItem(item);
|
||||
}
|
||||
|
||||
this.DiagnosticsOutlineView.AddItem(errors);
|
||||
this.DiagnosticsOutlineView.AddItem(warnings);
|
||||
this.DiagnosticsOutlineView.AddItem(infos);
|
||||
|
||||
this.DiagnosticsOutlineView.ReloadData();
|
||||
this.DiagnosticsOutlineView.ExpandItem(null, true);
|
||||
this.DiagnosticsOutlineView.UsesAutomaticRowHeights = true;
|
||||
}
|
||||
}
|
||||
}
|
26
Cauldron.Macos/DiagnosticsPopoverController.designer.cs
generated
Normal file
26
Cauldron.Macos/DiagnosticsPopoverController.designer.cs
generated
Normal file
|
@ -0,0 +1,26 @@
|
|||
// WARNING
|
||||
//
|
||||
// This file has been generated automatically by Visual Studio to store outlets and
|
||||
// actions made in the UI designer. If it is removed, they will be lost.
|
||||
// Manual changes to this file may not be handled correctly.
|
||||
//
|
||||
using Foundation;
|
||||
using System.CodeDom.Compiler;
|
||||
|
||||
namespace Cauldron.Macos
|
||||
{
|
||||
[Register ("DiagnosticsPopoverController")]
|
||||
partial class DiagnosticsPopoverController
|
||||
{
|
||||
[Outlet]
|
||||
Cauldron.Macos.SourceList.SourceListView DiagnosticsOutlineView { get; set; }
|
||||
|
||||
void ReleaseDesignerOutlets ()
|
||||
{
|
||||
if (DiagnosticsOutlineView != null) {
|
||||
DiagnosticsOutlineView.Dispose ();
|
||||
DiagnosticsOutlineView = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -411,6 +411,104 @@
|
|||
</objects>
|
||||
<point key="canvasLocation" x="-23" y="-256"/>
|
||||
</scene>
|
||||
<!--DiagnosticsPopoverController-->
|
||||
<scene sceneID="acn-Kt-JQh">
|
||||
<objects>
|
||||
<viewController id="kEs-j4-U6W" userLabel="DiagnosticsPopoverController" customClass="DiagnosticsPopoverController" sceneMemberID="viewController">
|
||||
<scrollView key="view" borderType="none" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="Hks-2F-bUK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" drawsBackground="NO" id="cqn-04-hFK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="sourceList" selectionHighlightStyle="sourceList" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" usesAutomaticRowHeights="YES" viewBased="YES" floatsGroupRows="NO" indentationPerLevel="13" outlineTableColumn="5vQ-lc-XSU" id="ueH-VL-qmi" customClass="SourceListView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="3" height="0.0"/>
|
||||
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn identifier="AutomaticTableColumnIdentifier.0" editable="NO" width="418" minWidth="16" maxWidth="1000" id="5vQ-lc-XSU">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" selectable="YES" editable="YES" title="Text Cell" id="44O-Er-1Ow">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="HeaderCell" id="hIJ-c2-KZG">
|
||||
<rect key="frame" x="11" y="0.0" width="427" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VUY-g0-yC7">
|
||||
<rect key="frame" x="0.0" y="1" width="427" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Header Cell" id="fCl-Sq-iCT">
|
||||
<font key="font" metaFont="systemMedium" size="11"/>
|
||||
<color key="textColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outlet property="textField" destination="VUY-g0-yC7" id="fMF-Z0-GSj"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
<tableCellView identifier="DataCell" id="5UQ-dL-kb2">
|
||||
<rect key="frame" x="11" y="17" width="427" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pak-Mk-Lui">
|
||||
<rect key="frame" x="3" y="0.0" width="17" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" imageScaling="proportionallyDown" image="NSActionTemplate" id="0eY-jA-bCa"/>
|
||||
</imageView>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Zl8-zy-VvA">
|
||||
<rect key="frame" x="25" y="0.0" width="402" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="Lea-Pq-teY">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="pak-Mk-Lui" id="QDN-q6-DTm"/>
|
||||
<outlet property="textField" destination="Zl8-zy-VvA" id="aRe-EC-mDA"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
</outlineView>
|
||||
</subviews>
|
||||
<nil key="backgroundColor"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="fHS-rH-sWS">
|
||||
<rect key="frame" x="0.0" y="284" width="450" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="gIS-un-96x">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<connections>
|
||||
<outlet property="DiagnosticOutlineView" destination="ueH-VL-qmi" id="lAb-PB-nvq"/>
|
||||
<outlet property="DiagnosticsOutlineView" destination="ueH-VL-qmi" id="D3c-Go-QWV"/>
|
||||
<outlet property="DiagnotsicsOutlineView" destination="ueH-VL-qmi" id="Jcw-Pp-kBT"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<customObject id="o6s-n2-s36" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-747" y="514"/>
|
||||
</scene>
|
||||
<!--Window Controller-->
|
||||
<scene sceneID="ktg-sd-7li">
|
||||
<objects>
|
||||
|
@ -435,25 +533,30 @@
|
|||
<toolbarItem implicitItemIdentifier="8EDDDA98-E8C5-404C-9832-8C97B1DAEF5C" label="Run Script" paletteLabel="Run Script" tag="-1" image="play.fill" catalog="system" bordered="YES" sizingBehavior="auto" autovalidates="NO" id="BH3-uw-K5S"/>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="ib2-fU-LMb"/>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="GqC-ht-JU0"/>
|
||||
<toolbarItem implicitItemIdentifier="1FDD22AF-AF38-4957-AC69-1E8377E11C5D" label="Script Status" paletteLabel="Script Status" bordered="YES" sizingBehavior="auto" autovalidates="NO" id="bj4-Kg-7Qc">
|
||||
<toolbarItem implicitItemIdentifier="1FDD22AF-AF38-4957-AC69-1E8377E11C5D" label="Diagnostics" paletteLabel="Diagnostics" bordered="YES" autovalidates="NO" id="bj4-Kg-7Qc">
|
||||
<nil key="toolTip"/>
|
||||
<segmentedControl key="view" verticalHuggingPriority="750" id="63L-Ya-hDW">
|
||||
<size key="minSize" width="114" height="23"/>
|
||||
<size key="maxSize" width="150" height="26"/>
|
||||
<segmentedControl key="view" identifier="DiagnosticsButtons" verticalHuggingPriority="750" id="63L-Ya-hDW">
|
||||
<rect key="frame" x="0.0" y="14" width="114" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<segmentedCell key="cell" borderStyle="border" alignment="left" style="texturedRounded" trackingMode="momentary" id="cZb-8H-XcB" customClass="ScriptStatusToolbarItem">
|
||||
<font key="font" metaFont="system"/>
|
||||
<segments>
|
||||
<segment label="0" alignment="left" width="32">
|
||||
<segment label="0" alignment="left" width="32" enabled="NO">
|
||||
<imageReference key="image" image="info.circle.fill" catalog="system" symbolScale="medium" renderingMode="original"/>
|
||||
</segment>
|
||||
<segment label="0" alignment="left" width="32" tag="1">
|
||||
<segment label="0" alignment="left" width="32" enabled="NO" tag="1">
|
||||
<imageReference key="image" image="exclamationmark.triangle.fill" catalog="system" symbolScale="medium" renderingMode="original"/>
|
||||
</segment>
|
||||
<segment label="0" alignment="left" toolTip="Error">
|
||||
<segment label="0" alignment="left" toolTip="Error" enabled="NO">
|
||||
<imageReference key="image" image="exclamationmark.circle.fill" catalog="system" symbolScale="medium" renderingMode="original"/>
|
||||
</segment>
|
||||
</segments>
|
||||
</segmentedCell>
|
||||
<connections>
|
||||
<segue destination="kEs-j4-U6W" kind="popover" popoverAnchorView="63L-Ya-hDW" popoverBehavior="t" preferredEdge="maxY" id="q8J-cg-E0J"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
</toolbarItem>
|
||||
</allowedToolbarItems>
|
||||
|
@ -478,7 +581,7 @@
|
|||
<customObject id="Dyo-ea-3jV" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<objectController mode="entity" entityName="CSharpScriptDocument" automaticallyPreparesContent="YES" id="IPo-2l-BeA"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-23" y="73"/>
|
||||
<point key="canvasLocation" x="-23.5" y="72.5"/>
|
||||
</scene>
|
||||
<!--Split View Controller-->
|
||||
<scene sceneID="BCF-ui-EPb">
|
||||
|
@ -531,18 +634,18 @@
|
|||
<objects>
|
||||
<viewController id="7dz-Mm-ph3" sceneMemberID="viewController">
|
||||
<scrollView key="view" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" id="uWO-6X-rW0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="300"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="400"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<clipView key="contentView" drawsBackground="NO" id="v6T-mX-paQ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="300"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="400"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView wantsLayer="YES" importsGraphics="NO" richText="NO" horizontallyResizable="YES" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="rAS-np-zOl" customClass="SourceTextView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="300"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="400"/>
|
||||
<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="300"/>
|
||||
<size key="minSize" width="700" height="400"/>
|
||||
<size key="maxSize" width="700" height="10000000"/>
|
||||
<attributedString key="textStorage">
|
||||
<fragment content="Cauldron">
|
||||
|
@ -585,7 +688,7 @@
|
|||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="S8X-st-Qy9">
|
||||
<rect key="frame" x="684" y="0.0" width="16" height="300"/>
|
||||
<rect key="frame" x="684" y="0.0" width="16" height="400"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
|
@ -599,7 +702,7 @@
|
|||
<objects>
|
||||
<viewController id="71j-pP-grU" sceneMemberID="viewController">
|
||||
<wkWebView key="view" wantsLayer="YES" id="8OW-Al-ci0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="300"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="200"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<wkWebViewConfiguration key="configuration">
|
||||
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||
|
@ -638,6 +741,7 @@
|
|||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="NSActionTemplate" width="20" height="20"/>
|
||||
<image name="exclamationmark.circle.fill" catalog="system" width="15" height="15"/>
|
||||
<image name="exclamationmark.triangle.fill" catalog="system" width="17" height="15"/>
|
||||
<image name="info.circle.fill" catalog="system" width="15" height="15"/>
|
||||
|
|
|
@ -55,6 +55,7 @@ public partial class MainWindow : NSWindowController
|
|||
#region Shared properties
|
||||
|
||||
public CancellationTokenSource ScriptCancellationTokenSource { get; set; }
|
||||
public ImmutableArray<Diagnostic> Diagnostics { get; set; } = ImmutableArray<Diagnostic>.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -92,6 +93,24 @@ public partial class MainWindow : NSWindowController
|
|||
this.SetDocumentEdited(this.ScriptDocument.IsDocumentEdited);
|
||||
}
|
||||
|
||||
public override void PrepareForSegue(NSStoryboardSegue segue, NSObject sender)
|
||||
{
|
||||
base.PrepareForSegue(segue, sender);
|
||||
|
||||
if (sender is NSSegmentedControl segmentedControl
|
||||
&& segmentedControl.Identifier == "DiagnosticsButtons"
|
||||
&& segue.DestinationController is DiagnosticsPopoverController diagPopover)
|
||||
{
|
||||
diagPopover.Severity = segmentedControl.SelectedSegment switch
|
||||
{
|
||||
0 => DiagnosticSeverity.Info,
|
||||
1 => DiagnosticSeverity.Warning,
|
||||
2 => DiagnosticSeverity.Error,
|
||||
_ => DiagnosticSeverity.Info
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateDocument(object sender, EventArgs args)
|
||||
{
|
||||
this.ScriptDocument.ScriptText = new NSString(this.ScriptText);
|
||||
|
@ -113,13 +132,10 @@ public partial class MainWindow : NSWindowController
|
|||
this.ScriptCancellationTokenSource?.Cancel();
|
||||
}
|
||||
|
||||
partial void NewTabMenuItemClicked(AppKit.NSMenuItem sender)
|
||||
{
|
||||
this.CreateNewTab();
|
||||
}
|
||||
|
||||
public void UpdateScriptDiagnostics(ImmutableArray<Diagnostic> diagnostics)
|
||||
{
|
||||
this.Diagnostics = diagnostics;
|
||||
|
||||
ImmutableList<Diagnostic> infoDiagnostics = diagnostics
|
||||
.Where(d => d.Severity == DiagnosticSeverity.Info)
|
||||
.ToImmutableList();
|
||||
|
@ -131,9 +147,15 @@ public partial class MainWindow : NSWindowController
|
|||
.ToImmutableList();
|
||||
|
||||
this.DiagnosticsToolbarGroup.SetLabel(infoDiagnostics.Count.ToString(), 0);
|
||||
this.DiagnosticsToolbarGroup.SetLabel(warningDiagnostics.Count.ToString(), 1);
|
||||
this.DiagnosticsToolbarGroup.SetLabel(errorDiagnostics.Count.ToString(), 2);
|
||||
this.DiagnosticsToolbarGroup.SetEnabled(infoDiagnostics.Count != 0, 0);
|
||||
|
||||
this.DiagnosticsToolbarGroup.SetLabel(warningDiagnostics.Count.ToString(), 1);
|
||||
this.DiagnosticsToolbarGroup.SetEnabled(warningDiagnostics.Count != 0, 1);
|
||||
|
||||
this.DiagnosticsToolbarGroup.SetLabel(errorDiagnostics.Count.ToString(), 2);
|
||||
this.DiagnosticsToolbarGroup.SetEnabled(errorDiagnostics.Count != 0, 2);
|
||||
|
||||
// Mark text in the
|
||||
foreach (Diagnostic diagnostic in diagnostics)
|
||||
{
|
||||
int start = diagnostic.Location.SourceSpan.Start;
|
||||
|
@ -161,7 +183,7 @@ public partial class MainWindow : NSWindowController
|
|||
range);
|
||||
else if (diagnostic.Severity == DiagnosticSeverity.Warning)
|
||||
this.ScriptEditorTextBox.LayoutManager
|
||||
.AddTemporaryAttribute(NSStringAttributeKey.UnderlineColor, NSColor.SystemGreen,
|
||||
.AddTemporaryAttribute(NSStringAttributeKey.UnderlineColor, NSColor.SystemYellow,
|
||||
range);
|
||||
else if (diagnostic.Severity == DiagnosticSeverity.Info)
|
||||
this.ScriptEditorTextBox.LayoutManager
|
||||
|
@ -181,12 +203,4 @@ public partial class MainWindow : NSWindowController
|
|||
this.RunScriptToolbarButton.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateNewTab()
|
||||
{
|
||||
MainWindow newWindow = this.Storyboard.InstantiateInitialController()
|
||||
as MainWindow;
|
||||
this.Window.AddTabbedWindow(newWindow.Window, NSWindowOrderingMode.Above);
|
||||
this.Window.SelectNextTab(this);
|
||||
}
|
||||
}
|
||||
|
|
19
Cauldron.Macos/MainWindow.designer.cs
generated
19
Cauldron.Macos/MainWindow.designer.cs
generated
|
@ -21,26 +21,17 @@ namespace Cauldron.Macos
|
|||
[Action ("BtnRunScriptClicked:")]
|
||||
partial void BtnRunScriptClicked (AppKit.NSToolbarItem sender);
|
||||
|
||||
[Action ("NewTabClicked:")]
|
||||
partial void NewTabClicked (AppKit.NSToolbarItem sender);
|
||||
|
||||
[Action ("NewTabMenuItemClicked:")]
|
||||
partial void NewTabMenuItemClicked (AppKit.NSMenuItem sender);
|
||||
|
||||
[Action ("NewTabMenuItemClicked2:")]
|
||||
partial void NewTabMenuItemClicked2 (AppKit.NSMenuItem sender);
|
||||
|
||||
void ReleaseDesignerOutlets ()
|
||||
{
|
||||
if (RunScriptToolbarButton != null) {
|
||||
RunScriptToolbarButton.Dispose ();
|
||||
RunScriptToolbarButton = null;
|
||||
}
|
||||
|
||||
if (DiagnosticsToolbarGroup != null) {
|
||||
DiagnosticsToolbarGroup.Dispose ();
|
||||
DiagnosticsToolbarGroup = null;
|
||||
}
|
||||
|
||||
if (RunScriptToolbarButton != null) {
|
||||
RunScriptToolbarButton.Dispose ();
|
||||
RunScriptToolbarButton = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
96
Cauldron.Macos/SourceList/SourceListDataSource.cs
Normal file
96
Cauldron.Macos/SourceList/SourceListDataSource.cs
Normal file
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using AppKit;
|
||||
using Foundation;
|
||||
|
||||
namespace Cauldron.Macos.SourceList
|
||||
{
|
||||
public class SourceListDataSource : NSOutlineViewDataSource
|
||||
{
|
||||
#region Private Variables
|
||||
|
||||
private SourceListView _controller;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Variables
|
||||
|
||||
public List<SourceListItem> Items = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public SourceListDataSource(SourceListView controller)
|
||||
{
|
||||
// Initialize
|
||||
this._controller = controller;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Override Properties
|
||||
|
||||
public override nint GetChildrenCount(NSOutlineView outlineView, Foundation.NSObject item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return Items.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((SourceListItem)item).Count;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ItemExpandable(NSOutlineView outlineView, Foundation.NSObject item)
|
||||
{
|
||||
return ((SourceListItem)item).HasChildren;
|
||||
}
|
||||
|
||||
public override NSObject GetChild(NSOutlineView outlineView, nint childIndex, Foundation.NSObject item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return Items[(int)childIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((SourceListItem)item)[(int)childIndex];
|
||||
}
|
||||
}
|
||||
|
||||
public override NSObject GetObjectValue(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
|
||||
{
|
||||
return new NSString(((SourceListItem)item).Title);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal SourceListItem ItemForRow(int row)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
// Look at each group
|
||||
foreach (SourceListItem item in Items)
|
||||
{
|
||||
// Is the row inside this group?
|
||||
if (row >= index && row <= (index + item.Count))
|
||||
{
|
||||
return item[row - index - 1];
|
||||
}
|
||||
|
||||
// Move index
|
||||
index += item.Count + 1;
|
||||
}
|
||||
|
||||
// Not found
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
112
Cauldron.Macos/SourceList/SourceListDelegate.cs
Normal file
112
Cauldron.Macos/SourceList/SourceListDelegate.cs
Normal file
|
@ -0,0 +1,112 @@
|
|||
using AppKit;
|
||||
using CoreGraphics;
|
||||
using Foundation;
|
||||
|
||||
namespace Cauldron.Macos.SourceList
|
||||
{
|
||||
public class SourceListDelegate : NSOutlineViewDelegate
|
||||
{
|
||||
#region Private variables
|
||||
|
||||
private SourceListView _controller;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public SourceListDelegate(SourceListView controller)
|
||||
{
|
||||
this._controller = controller;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
|
||||
public override bool ShouldEditTableColumn(NSOutlineView outlineView,
|
||||
NSTableColumn tableColumn, NSObject item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override NSCell GetCell(NSOutlineView outlineView, NSTableColumn tableColumn,
|
||||
NSObject item)
|
||||
{
|
||||
nint row = outlineView.RowForItem(item);
|
||||
return tableColumn.DataCellForRow(row);
|
||||
}
|
||||
|
||||
public override bool IsGroupItem(NSOutlineView outlineView, NSObject item)
|
||||
{
|
||||
return ((SourceListItem)item).HasChildren;
|
||||
}
|
||||
|
||||
public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn,
|
||||
NSObject item)
|
||||
{
|
||||
NSTableCellView view;
|
||||
|
||||
// Is this a group item?
|
||||
if (((SourceListItem)item).IsHeader)
|
||||
{
|
||||
view = (NSTableCellView)outlineView.MakeView("HeaderCell", this);
|
||||
}
|
||||
else
|
||||
{
|
||||
view = (NSTableCellView)outlineView.MakeView("DataCell", this);
|
||||
view.ImageView.Image = ((SourceListItem)item).Icon;
|
||||
view.TextField.LineBreakMode = NSLineBreakMode.CharWrapping;
|
||||
view.TextField.UsesSingleLineMode = false;
|
||||
view.TextField.MaximumNumberOfLines = 0;
|
||||
}
|
||||
|
||||
view.TextField.StringValue = ((SourceListItem)item).Title;
|
||||
view.TextField.SetBoundsSize(CalculateTextFieldHeight(view));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
public override bool ShouldSelectItem(NSOutlineView outlineView, NSObject item)
|
||||
{
|
||||
return (outlineView.GetParent(item) != null);
|
||||
}
|
||||
|
||||
public override void SelectionDidChange(NSNotification notification)
|
||||
{
|
||||
NSIndexSet selectedIndexes = _controller.SelectedRows;
|
||||
|
||||
// More than one item selected?
|
||||
if (selectedIndexes.Count > 1)
|
||||
{
|
||||
// Not handling this case
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the item
|
||||
var item = _controller.Data.ItemForRow((int)selectedIndexes.FirstIndex);
|
||||
|
||||
// Was an item found?
|
||||
if (item != null)
|
||||
{
|
||||
// Fire the clicked event for the item
|
||||
item.RaiseClickedEvent();
|
||||
|
||||
// Inform caller of selection
|
||||
_controller.RaiseItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static CGSize CalculateTextFieldHeight(NSTableCellView cell)
|
||||
{
|
||||
CGRect rect = new(0, 0, cell.TextField.Bounds.Width, double.MaxValue);
|
||||
NSString str = new(cell.TextField.StringValue);
|
||||
CGRect bounds = str.BoundingRectWithSize(rect.Size, 0,
|
||||
new NSDictionary(NSStringAttributeKey.Font, cell.TextField.Font));
|
||||
|
||||
return new CGSize(cell.TextField.Bounds.Width, bounds.Size.Height);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
241
Cauldron.Macos/SourceList/SourceListItem.cs
Normal file
241
Cauldron.Macos/SourceList/SourceListItem.cs
Normal file
|
@ -0,0 +1,241 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using AppKit;
|
||||
using Foundation;
|
||||
|
||||
namespace Cauldron.Macos.SourceList
|
||||
{
|
||||
public class SourceListItem : NSObject, IEnumerator, IEnumerable
|
||||
{
|
||||
#region Private Properties
|
||||
|
||||
private string _title;
|
||||
private NSImage _icon;
|
||||
private string _tag;
|
||||
private bool _isHeader = false;
|
||||
private List<SourceListItem> _items = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Computed Properties
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return _title; }
|
||||
set { _title = value; }
|
||||
}
|
||||
|
||||
public NSImage Icon
|
||||
{
|
||||
get { return _icon; }
|
||||
set { _icon = value; }
|
||||
}
|
||||
|
||||
public string Tag
|
||||
{
|
||||
get { return _tag; }
|
||||
set { _tag = value; }
|
||||
}
|
||||
|
||||
public bool IsHeader
|
||||
{
|
||||
get => this._isHeader;
|
||||
set => this._isHeader = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Indexer
|
||||
|
||||
public SourceListItem this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _items[index];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_items[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return _items.Count; }
|
||||
}
|
||||
|
||||
public bool HasChildren
|
||||
{
|
||||
get { return (Count > 0); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enumerable Routines
|
||||
|
||||
private int _position = -1;
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
_position = -1;
|
||||
return (IEnumerator)this;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
_position++;
|
||||
return (_position < _items.Count);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{ _position = -1; }
|
||||
|
||||
public object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return _items[_position];
|
||||
}
|
||||
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public SourceListItem() { }
|
||||
|
||||
public SourceListItem(string title)
|
||||
{
|
||||
this._title = title;
|
||||
}
|
||||
|
||||
public SourceListItem(string title, string icon)
|
||||
{
|
||||
this._title = title;
|
||||
this._icon = NSImage.ImageNamed(icon);
|
||||
}
|
||||
|
||||
public SourceListItem(string title, string icon, ClickedDelegate clicked)
|
||||
{
|
||||
this._title = title;
|
||||
this._icon = NSImage.ImageNamed(icon);
|
||||
this.Clicked = clicked;
|
||||
}
|
||||
|
||||
public SourceListItem(string title, NSImage icon)
|
||||
{
|
||||
this._title = title;
|
||||
this._icon = icon;
|
||||
}
|
||||
|
||||
public SourceListItem(string title, NSImage icon, ClickedDelegate clicked)
|
||||
{
|
||||
this._title = title;
|
||||
this._icon = icon;
|
||||
this.Clicked = clicked;
|
||||
}
|
||||
|
||||
public SourceListItem(string title, NSImage icon, string tag)
|
||||
{
|
||||
this._title = title;
|
||||
this._icon = icon;
|
||||
this._tag = tag;
|
||||
}
|
||||
|
||||
public SourceListItem(string title, NSImage icon, string tag, ClickedDelegate clicked)
|
||||
{
|
||||
this._title = title;
|
||||
this._icon = icon;
|
||||
this._tag = tag;
|
||||
this.Clicked = clicked;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void AddItem(SourceListItem item)
|
||||
{
|
||||
_items.Add(item);
|
||||
}
|
||||
|
||||
public void AddItem(string title)
|
||||
{
|
||||
_items.Add(new SourceListItem(title));
|
||||
}
|
||||
|
||||
public void AddItem(string title, string icon)
|
||||
{
|
||||
_items.Add(new SourceListItem(title, icon));
|
||||
}
|
||||
|
||||
public void AddItem(string title, string icon, ClickedDelegate clicked)
|
||||
{
|
||||
_items.Add(new SourceListItem(title, icon, clicked));
|
||||
}
|
||||
|
||||
public void AddItem(string title, NSImage icon)
|
||||
{
|
||||
_items.Add(new SourceListItem(title, icon));
|
||||
}
|
||||
|
||||
public void AddItem(string title, NSImage icon, ClickedDelegate clicked)
|
||||
{
|
||||
_items.Add(new SourceListItem(title, icon, clicked));
|
||||
}
|
||||
|
||||
public void AddItem(string title, NSImage icon, string tag)
|
||||
{
|
||||
_items.Add(new SourceListItem(title, icon, tag));
|
||||
}
|
||||
|
||||
public void AddItem(string title, NSImage icon, string tag, ClickedDelegate clicked)
|
||||
{
|
||||
_items.Add(new SourceListItem(title, icon, tag, clicked));
|
||||
}
|
||||
|
||||
public void Insert(int n, SourceListItem item)
|
||||
{
|
||||
_items.Insert(n, item);
|
||||
}
|
||||
|
||||
public void RemoveItem(SourceListItem item)
|
||||
{
|
||||
_items.Remove(item);
|
||||
}
|
||||
|
||||
public void RemoveItem(int n)
|
||||
{
|
||||
_items.RemoveAt(n);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_items.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public delegate void ClickedDelegate();
|
||||
public event ClickedDelegate Clicked;
|
||||
|
||||
internal void RaiseClickedEvent()
|
||||
{
|
||||
this.Clicked?.Invoke();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
69
Cauldron.Macos/SourceList/SourceListView.cs
Normal file
69
Cauldron.Macos/SourceList/SourceListView.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using AppKit;
|
||||
using Foundation;
|
||||
|
||||
namespace Cauldron.Macos.SourceList
|
||||
{
|
||||
[Register("SourceListView")]
|
||||
public class SourceListView : NSOutlineView
|
||||
{
|
||||
#region Computed Properties
|
||||
|
||||
public SourceListDataSource Data
|
||||
{
|
||||
get { return (SourceListDataSource)this.DataSource; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public SourceListView() { }
|
||||
|
||||
public SourceListView(IntPtr handle) : base(handle) { }
|
||||
|
||||
public SourceListView(NSCoder coder) : base(coder) { }
|
||||
|
||||
public SourceListView(NSObjectFlag t) : base(t) { }
|
||||
|
||||
public SourceListView(ObjCRuntime.NativeHandle handle) : base(handle) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
|
||||
public override void AwakeFromNib()
|
||||
{
|
||||
base.AwakeFromNib();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
this.DataSource = new SourceListDataSource(this);
|
||||
this.Delegate = new SourceListDelegate(this);
|
||||
}
|
||||
|
||||
public void AddItem(SourceListItem item)
|
||||
{
|
||||
Data?.Items.Add(item);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public delegate void ItemSelectedDelegate(SourceListItem item);
|
||||
public event ItemSelectedDelegate ItemSelected;
|
||||
|
||||
internal void RaiseItemSelected(SourceListItem item)
|
||||
{
|
||||
this.ItemSelected?.Invoke(item);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue