3D Scene Styles
- SetBasemap(2))" />
-
+ SetBasemap(2))"/>
+
@if (_basemapType == 2)
{
@@ -60,7 +62,7 @@
From Portal Id
SetBasemap(3))" />
+ name="basemap-type" @onclick="@(() => SetBasemap(3))"/>
@if (_basemapType == 3)
@@ -84,7 +86,7 @@
From Tile Layers
SetBasemap(4))" />
+ name="basemap-type" @onclick="@(() => SetBasemap(4))"/>
World Hillshade Tile Layer
@@ -114,10 +116,11 @@
-
+
+
break;
case 3:
@@ -157,7 +160,7 @@
_basemapStyleName = (BasemapStyleName)Enum.Parse(typeof(BasemapStyleName), obj.Value!.ToString()!, true);
await _mapView1!.Refresh();
}
-
+
private async Task SelectSceneStyleMapChanged(ChangeEventArgs obj)
{
_basemapStyleName = (BasemapStyleName)Enum.Parse(typeof(BasemapStyleName), obj.Value!.ToString()!, true);
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/HitTests.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/HitTests.razor
index 4187d614a..d82effc2e 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/HitTests.razor
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/HitTests.razor
@@ -64,7 +64,7 @@
{
HitTestOptions options = new()
{
- IncludeByGeoBlazorId = new[] { _hurricaneLayer!.Id }
+ IncludeByGeoBlazorId = [_hurricaneLayer!.Id]
};
HitTestResult result = await _mapView!.HitTest(pointerEvent, options);
Graphic? graphic = result.Results.OfType().FirstOrDefault()?.Graphic;
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Home.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Home.razor
index b97da9cbd..2895eeec7 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Home.razor
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Home.razor
@@ -43,7 +43,7 @@
protected override void OnInitialized()
{
base.OnInitialized();
-
+
Console.WriteLine(PageRoute);
}
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ManyGraphics.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ManyGraphics.razor
index 1caf501aa..4784210d9 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ManyGraphics.razor
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ManyGraphics.razor
@@ -52,7 +52,7 @@
{
if (firstRender)
{
- _chunkSize = _view?.IsMaui == true ? 100 : 200;
+ _chunkSize = IsMaui ? 100 : 200;
}
}
@@ -178,4 +178,5 @@
private string _geometryType = "Point";
private readonly List _graphics = new();
private bool _generating;
+ private bool IsMaui => _view?.JsRuntime!.GetType().Name.Contains("WebView") ?? false;
}
\ No newline at end of file
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServerSideQueries.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServerSideQueries.razor
index c1c7751c6..8f5dfad64 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServerSideQueries.razor
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServerSideQueries.razor
@@ -11,10 +11,9 @@
+ OnLayerViewCreate="OnLayerViewCreate"
+ Class="map-view">
@@ -29,7 +28,7 @@
Ymin="4536523.6511999965">
-
+
@@ -50,68 +49,55 @@
-
@code {
+
+ [Inject]
+ public required IJSRuntime JsRuntime { get; set; }
private async Task OnLayerViewCreate(LayerViewCreateEvent createEvent)
{
if (createEvent.Layer?.Id == _featureLayer?.Id)
{
- PopupTemplate popupTemplate = await _featureLayer!.CreatePopupTemplate();
- await _featureLayer!.SetPopupTemplate(popupTemplate);
await _mapView!.SetExtent(_featureLayer!.FullExtent!);
}
}
private async Task OnClick(ClickEvent clickEvent)
{
- var query = new Query
- {
- Geometry = clickEvent.MapPoint,
- Distance = Distance,
- Units = Unit,
- SpatialRelationship = SpatialRelationship.Intersects,
- ReturnGeometry = false,
- ReturnQueryGeometry = true,
- OutFields = new HashSet { "*" }
- };
+ Query query = await _featureLayer!.CreateQuery();
+ query.Geometry = clickEvent.MapPoint;
+ query.Distance = Distance;
+ query.Units = Unit;
+ query.SpatialRelationship = SpatialRelationship.Intersects;
+ query.ReturnGeometry = true;
+ query.ReturnQueryGeometry = true;
+ query.OutFields = ["*"];
+
FeatureSet result = (await _featureLayer!.QueryFeatures(query))!;
- await _pointGraphic.SetGeometry(clickEvent.MapPoint);
- if (!_mapView!.Graphics.Contains(_pointGraphic))
- {
- await _mapView.AddGraphic(_pointGraphic);
- }
+ await _mapView!.ClearGraphics();
+ Graphic pointGraphic = new(clickEvent.MapPoint, _markerSymbol);
- if (result.QueryGeometry is not null)
+ if (_queryType == "distance")
{
- await _bufferGraphic.SetGeometry(result.QueryGeometry);
- if (!_mapView.Graphics.Contains(_bufferGraphic))
- {
- await _mapView.AddGraphic(_bufferGraphic);
- }
+ Graphic buffer = new(result.QueryGeometry, _bufferSymbol);
+ await _mapView.AddGraphics([pointGraphic, buffer]);
}
- else if (_mapView.Graphics.Contains(_bufferGraphic))
+ else
{
- await _mapView.RemoveGraphic(_bufferGraphic);
+ await _mapView.AddGraphic(pointGraphic);
}
- await _mapView.OpenPopup(new PopupOpenOptions
- {
- Location = clickEvent.MapPoint,
- Features = result.Features,
- FeatureMenuOpen = true
- });
+ await _popup!.SetFeatures(result.Features);
}
private double? Distance => _queryType == "distance" ? 0.5 : null;
private QueryUnits? Unit => _queryType == "distance" ? QueryUnits.Miles : null;
private MapView? _mapView;
+ private PopupWidget? _popup;
private FeatureLayer? _featureLayer;
- private readonly Graphic _pointGraphic = new(symbol: new SimpleMarkerSymbol(
- new Outline(new MapColor(255, 255, 255), 1),
- new MapColor(0, 0, 139)));
- private readonly Graphic _bufferGraphic = new(symbol: new SimpleFillSymbol(
- new Outline(new MapColor(255, 255, 255), 1.5),
- new MapColor(173, 216, 230, 0.2)));
+ private readonly SimpleMarkerSymbol _markerSymbol = new(new Outline(new MapColor(255, 255, 255), 1),
+ new MapColor(0, 0, 139));
+ private readonly SimpleFillSymbol _bufferSymbol = new(new Outline(new MapColor(255, 255, 255), 1.5),
+ new MapColor(173, 216, 230, 0.2));
private string? _queryType;
}
\ No newline at end of file
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Tests.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Tests.razor
index 4690fc13a..083e1309a 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Tests.razor
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Tests.razor
@@ -148,29 +148,27 @@
}
private MapView? _view;
- private readonly FeatureLayer _localFeatureLayer = new(source: new[]
- {
- new Graphic(new Point(11.967162, 49.201448),
+ private readonly FeatureLayer _localFeatureLayer = new(source:
+ [
+ new Graphic(new Point(11.967162, 49.201448),
new SimpleMarkerSymbol(new Outline(new MapColor("white")),
new MapColor("red"), 6))
- },
+ ],
objectIdField: "OBJECTID");
private readonly FeatureLayer _remoteFeatureLayer =
new("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/weather_stations_010417/FeatureServer/0");
- private readonly GraphicsLayer _graphicsLayer = new(new[]
- {
+ private readonly GraphicsLayer _graphicsLayer = new([
new Graphic(new Point(11.888650, 52.451825),
new SimpleMarkerSymbol(new Outline(new MapColor("white")),
new MapColor("green"), 6)),
- new Graphic(new Polyline(new[]
- {
- new MapPath(new MapPoint(11, 52),
+ new Graphic(new Polyline([
+ new MapPath(new MapPoint(11, 52),
new MapPoint(11.5, 53),
new MapPoint(12, 55),
new MapPoint(10, 55),
new MapPoint(10.5, 51),
new MapPoint(11, 56))
- }),
+ ]),
new SimpleLineSymbol(new MapColor("blue"), 2)),
new Graphic(new Point(7.274721, 59.614991),
new PictureMarkerSymbol("https://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png",
@@ -178,7 +176,7 @@
new Graphic(new Point(29.437639, 55.469513),
new TextSymbol("Hello World", new MapColor("red"),
new MapColor("yellow"), 12))
- });
+ ]);
private async void On3Click(ClickEvent clickEvent)
{
@@ -206,8 +204,8 @@
private bool _map3Rendered;
private bool _showGraphicsMarkupLayer;
private readonly Random _random = new();
- private readonly List _lats = new() { 49.201448, 52.451825, 59.614991, 55.469513 };
- private readonly List _longs = new() { 11.967162, 11.888650, 7.274721, 29.437639 };
+ private readonly List _lats = [49.201448, 52.451825, 59.614991, 55.469513];
+ private readonly List _longs = [11.967162, 11.888650, 7.274721, 29.437639];
private MapView? _view3;
private int _graphicsCount = 1;
}
\ No newline at end of file
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WFSLayers.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WFSLayers.razor
index 16222843b..2a255ce61 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WFSLayers.razor
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WFSLayers.razor
@@ -9,6 +9,12 @@
To create a WFSLayer, all you need is the URL to a WFS service that supports WFS 2.0.0 and has GeoJSON output format enabled. Optionally, you can set the name to the FeatureType you want to access in the service. If no name is provided, the layer will default to the first FeatureType in the service.
+
+ Source: Office for National Statistics licensed under the Open Government Licence v.3.0
+
+
+ Contains OS data © Crown copyright and database right @DateTime.Now.Year
+
FilteredPages => string.IsNullOrWhiteSpace(SearchText)
? Pages
: Pages.Where(p => p.Title.Contains(SearchText, StringComparison.OrdinalIgnoreCase));
-
- public void Dispose()
- {
- _dotNetRef?.Dispose();
- }
-
- [JSInvokable]
- public void OnScroll(double scrollTop)
- {
- _scrollTop = scrollTop;
- }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
@@ -47,9 +36,12 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
string currentPage = NavigationManager
.ToBaseRelativePath(NavigationManager.Uri)
.Replace("source-code/", "");
- await JsRuntime.InvokeVoidAsync("scrollToNav", currentPage);
- _dotNetRef = DotNetObjectReference.Create(this);
- await JsRuntime.InvokeVoidAsync("trackScrollPosition", Navbar, _dotNetRef);
+
+ if (currentPage != string.Empty)
+ {
+ await JsRuntime.InvokeVoidAsync("scrollToNav", currentPage);
+ }
+
StateHasChanged();
}
@@ -89,8 +81,6 @@ await InvokeAsync(async () =>
protected virtual bool CollapseNavMenu { get; set; } = true;
protected ElementReference? Navbar;
- private DotNetObjectReference? _dotNetRef;
- private double _scrollTop;
public virtual PageLink[] Pages =>
[
new("", "Home", "oi-home"),
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/dymaptic.GeoBlazor.Core.Sample.Shared.csproj b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/dymaptic.GeoBlazor.Core.Sample.Shared.csproj
index b8d54a059..83447a3cc 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/dymaptic.GeoBlazor.Core.Sample.Shared.csproj
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/dymaptic.GeoBlazor.Core.Sample.Shared.csproj
@@ -10,11 +10,11 @@
-
+
-
-
-
+
+
+
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/functions.js b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/functions.js
index ee6861ed6..6615257b5 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/functions.js
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/functions.js
@@ -1,33 +1,4 @@
-let navbarRef;
-let navbar;
-
-window.trackScrollPosition = (navbarElem, dotNetRef) => {
- navbar = navbarElem;
- navbarRef = dotNetRef;
- navbar.addEventListener('scroll', onScroll);
- // Initial call to set the position
- _ = onScroll();
-}
-
-window.removeScrollTracking = () => {
- if (navbar) {
- navbar.removeEventListener('scroll', onScroll);
- navbar = null;
- }
- navbarRef = null;
-}
-
-window.scrollToPosition = (position) => {
- if (navbar) {
- navbar.scrollTop = position;
- }
-}
-
-async function onScroll() {
- await navbarRef.invokeMethodAsync('OnScroll', navbar.scrollTop);
-}
-
-window.scrollToNav = (page) => {
+window.scrollToNav = (page) => {
let navItems = document.getElementsByTagName('a');
let navItem = Array.from(navItems).find(i => i.href.endsWith(page));
if (navigator.userAgent.indexOf('Firefox') === -1) {
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client.csproj b/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client.csproj
index 98e718efe..81c1ffe44 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client.csproj
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client.csproj
@@ -1,17 +1,15 @@
- net10.0
- enable
- enable
+ net10.0
true
Default
-
-
-
+
+
+
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/Components/Routes.razor b/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/Components/Routes.razor
index 53fa070e4..0c2880801 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/Components/Routes.razor
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/Components/Routes.razor
@@ -1,8 +1,9 @@
-
-
+
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/Program.cs b/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/Program.cs
index 61b0a498b..f4d637901 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/Program.cs
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/Program.cs
@@ -1,7 +1,8 @@
using dymaptic.GeoBlazor.Core;
-using dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Components;
using dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Apis;
using dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client.Services;
+using dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Components;
+using _Imports = dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client._Imports;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
@@ -38,6 +39,6 @@
app.MapRazorComponents()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
- .AddAdditionalAssemblies(typeof(dymaptic.GeoBlazor.Core.Sample.TokenRefresh.Client._Imports).Assembly);
+ .AddAdditionalAssemblies(typeof(_Imports).Assembly);
-app.Run();
+app.Run();
\ No newline at end of file
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.csproj b/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.csproj
index 41031a06f..07dfbd614 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.csproj
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh/dymaptic.GeoBlazor.Core.Sample.TokenRefresh.csproj
@@ -1,16 +1,14 @@
- net10.0
- enable
- enable
+ net10.0
09852c49-58ad-4029-956b-1e18661fd6b3
-
+
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Wasm/dymaptic.GeoBlazor.Core.Sample.Wasm.csproj b/samples/dymaptic.GeoBlazor.Core.Sample.Wasm/dymaptic.GeoBlazor.Core.Sample.Wasm.csproj
index b877c7e6a..60b8c4c69 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.Wasm/dymaptic.GeoBlazor.Core.Sample.Wasm.csproj
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.Wasm/dymaptic.GeoBlazor.Core.Sample.Wasm.csproj
@@ -5,8 +5,8 @@
-
-
+
+
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/Routes.razor b/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/Routes.razor
index 5dac2a9d0..0866abc7d 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/Routes.razor
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/Routes.razor
@@ -1,5 +1,5 @@
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/dymaptic.GeoBlazor.Core.Sample.WebApp.Client.csproj b/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/dymaptic.GeoBlazor.Core.Sample.WebApp.Client.csproj
index 113dfc946..5fb04f61b 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/dymaptic.GeoBlazor.Core.Sample.WebApp.Client.csproj
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/dymaptic.GeoBlazor.Core.Sample.WebApp.Client.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.csproj b/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.csproj
index f14386c4d..e1ac12030 100644
--- a/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.csproj
+++ b/samples/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/showDialog.ps1 b/showDialog.ps1
deleted file mode 100644
index 4fb49eb31..000000000
--- a/showDialog.ps1
+++ /dev/null
@@ -1,760 +0,0 @@
-<#
-.SYNOPSIS
- Cross-platform dialog utility for displaying message boxes.
-
-.DESCRIPTION
- Shows a message dialog using platform-appropriate methods:
- - Windows: WinForms-based custom dialog
- - macOS: AppleScript display alert
- - Linux: zenity, kdialog, or console fallback
-
-.PARAMETER Message
- The message text to display in the dialog.
-
-.PARAMETER Title
- The title of the dialog window.
-
-.PARAMETER Buttons
- The button configuration. Valid values: None, OK, OKCancel, YesNo, YesNoCancel, RetryCancel, AbortRetryIgnore
- Use 'None' for a dialog that stays open until programmatically killed.
-
-.PARAMETER Type
- The dialog type which determines the color scheme. Valid values: information, warning, error, success
-
-.PARAMETER DefaultButtonIndex
- Zero-based index of the default button.
-
-.PARAMETER ListenForInput
- When specified, the dialog will listen for standard input and append each line received to the message.
- This allows external processes to update the dialog message dynamically while it's open.
- (Windows only)
-
-.EXAMPLE
- .\showDialog.ps1 -Message "Operation completed successfully" -Title "Success" -Type success
-
-.EXAMPLE
- .\showDialog.ps1 -Message "Are you sure?" -Title "Confirm" -Buttons YesNo -Type warning
-
-.EXAMPLE
- $result = .\showDialog.ps1 -Message "Continue?" -Title "Question" -Buttons YesNoCancel
- if ($result -eq "Yes") { Write-Host "User selected Yes" }
-
-.EXAMPLE
- # Start a persistent dialog in async mode, then kill it later
- $job = Start-Job { .\showDialog.ps1 -Message "Processing..." -Title "Please Wait" -Buttons None -Type information }
- # ... do work ...
- Stop-Job $job; Remove-Job $job
-
-.EXAMPLE
- # Use -ListenForInput to dynamically update the dialog message from stdin
- # Pipe output to the dialog to update its message in real-time
- & { Write-Output "Step 1 complete"; Start-Sleep 1; Write-Output "Step 2 complete" } | .\showDialog.ps1 -Message "Starting..." -Title "Progress" -Buttons None -ListenForInput
-#>
-
-param(
- [Parameter(Mandatory, Position = 0)]
- [string]$Message,
-
- [Parameter(Position = 1)]
- [string]$Title = "Message",
-
- [Parameter(Position = 2)]
- [ValidateSet('None', 'OK', 'OKCancel', 'YesNo', 'YesNoCancel', 'RetryCancel', 'AbortRetryIgnore')]
- [string]$Buttons = 'OK',
-
- [ValidateSet('information', 'warning', 'error', 'success')]
- [string]$Type = 'information',
-
- [ValidateSet(0, 1, 2)]
- [int]$DefaultButtonIndex = -1,
-
- [int]$Duration = 0,
-
- [switch]$Async,
-
- [switch]$ListenForInput
-)
-
-$buttonMap = @{
- 'None' = @{ buttonList = @(); defaultButtonIndex = -1; cancelButtonIndex = $null }
- 'OK' = @{ buttonList = @('OK'); defaultButtonIndex = 0; cancelButtonIndex = $null }
- 'OKCancel' = @{ buttonList = @('OK', 'Cancel'); defaultButtonIndex = 0; cancelButtonIndex = 1 }
- 'YesNo' = @{ buttonList = @('Yes', 'No'); defaultButtonIndex = 0; cancelButtonIndex = 1 }
- 'YesNoCancel' = @{ buttonList = @('Yes', 'No', 'Cancel'); defaultButtonIndex = 0; cancelButtonIndex = 2 }
- 'RetryCancel' = @{ buttonList = @('Retry', 'Cancel'); defaultButtonIndex = 0; cancelButtonIndex = 1 }
- 'AbortRetryIgnore' = @{ buttonList = @('Abort', 'Retry', 'Ignore'); defaultButtonIndex = 2; cancelButtonIndex = 0 }
-}
-
-function Show-WindowsDialog {
- param(
- [string]$Message,
- [string]$Title,
- [string]$Type,
- [string[]]$ButtonList,
- [int]$DefaultIndex,
- [int]$CancelIndex,
- [int]$Duration,
- [bool]$Async,
- [bool]$ListenForInput
- )
-
- # Create synchronized hashtable for cross-runspace communication
- $syncHash = [hashtable]::Synchronized(@{
- Message = $Message
- DialogClosed = $false
- Result = $null
- })
-
- $runspace = [runspacefactory]::CreateRunspace()
- $runspace.Open()
- $runspace.SessionStateProxy.SetVariable('syncHash', $syncHash)
-
- $PowerShell = [PowerShell]::Create().AddScript({
- param ($message, $title, $type, $buttonList, $defaultButtonIndex, $cancelButtonIndex, $duration, $syncHash)
-
- Add-Type -AssemblyName System.Windows.Forms
- Add-Type -AssemblyName System.Drawing
-
- # Win32 API for forcing window to foreground
- Add-Type @"
- using System;
- using System.Runtime.InteropServices;
- public class Win32 {
- [DllImport("user32.dll")]
- public static extern bool SetForegroundWindow(IntPtr hWnd);
-
- [DllImport("user32.dll")]
- public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
-
- [DllImport("user32.dll")]
- public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetForegroundWindow();
-
- [DllImport("user32.dll")]
- public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);
-
- [DllImport("kernel32.dll")]
- public static extern uint GetCurrentThreadId();
-
- [DllImport("user32.dll")]
- public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
-
- public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
- public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
- public const uint SWP_NOMOVE = 0x0002;
- public const uint SWP_NOSIZE = 0x0001;
- public const int SW_SHOW = 5;
- public const int SW_RESTORE = 9;
- }
-"@
-
- $Timer = New-Object System.Windows.Forms.Timer
- $Timer.Interval = 1000
- $script:result = $null
- $script:countdown = $duration
-
- # Color schemes based on type
- $colorSchemes = @{
- "success" = @{ back = "#60A917"; fore = "#FFFFFF" }
- "warning" = @{ back = "#FA6800"; fore = "#FFFFFF" }
- "information" = @{ back = "#693CB2"; fore = "#FFFFFF" }
- "error" = @{ back = "#CE352C"; fore = "#FFFFFF" }
- }
-
- $colors = if ($colorSchemes.ContainsKey($type)) { $colorSchemes[$type] } else { @{ back = "#FFFFFF"; fore = "#000000" } }
- $back = $colors.back
- $fore = $colors.fore
-
- # Build Form
- $form = New-Object System.Windows.Forms.Form
- $form.ShowInTaskbar = $false
- $form.TopMost = $true
- $form.Text = $title
- $form.ForeColor = [System.Drawing.ColorTranslator]::FromHtml($fore)
- $form.BackColor = [System.Drawing.ColorTranslator]::FromHtml($back)
- $form.ControlBox = $true
- $form.MinimizeBox = $false
- $form.MaximizeBox = $false
- $form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
-
- # Calculate dimensions
- $buttonHeight = 35
- $buttonMargin = 10
- $hasButtons = $buttonList.Count -gt 0
- $totalButtonHeight = if ($hasButtons) { $buttonHeight + ($buttonMargin * 2) } else { 0 }
- $formWidth = 400
- $formHeight = 480 + $totalButtonHeight
-
- $form.Size = New-Object System.Drawing.Size($formWidth, $formHeight)
-
- # Center on primary screen, with offset for other dialog instances
- $monitor = [System.Windows.Forms.Screen]::PrimaryScreen
- $monitorWidth = $monitor.WorkingArea.Width
- $monitorHeight = $monitor.WorkingArea.Height
-
- # Calculate base center position
- $baseCenterX = [int](($monitorWidth / 2) - ($form.Width / 2))
- $baseCenterY = [int](($monitorHeight / 2) - ($form.Height / 2))
-
- # Find other PowerShell-hosted forms by checking for windows at similar positions
- # Use a simple offset based on existing windows at the center position
- $offset = 0
- $offsetStep = 30
-
- # Get all visible top-level windows and check for overlaps
- Add-Type @"
- using System;
- using System.Collections.Generic;
- using System.Runtime.InteropServices;
- using System.Text;
-
- public class WindowFinder {
- [DllImport("user32.dll")]
- private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
-
- [DllImport("user32.dll")]
- private static extern bool IsWindowVisible(IntPtr hWnd);
-
- [DllImport("user32.dll")]
- private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
-
- [StructLayout(LayoutKind.Sequential)]
- public struct RECT {
- public int Left, Top, Right, Bottom;
- }
-
- private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
-
- public static List GetVisibleWindowRects() {
- List rects = new List();
- EnumWindows((hWnd, lParam) => {
- if (IsWindowVisible(hWnd)) {
- RECT rect;
- if (GetWindowRect(hWnd, out rect)) {
- // Only include reasonably sized windows (not tiny or huge)
- int width = rect.Right - rect.Left;
- int height = rect.Bottom - rect.Top;
- if (width > 100 && width < 800 && height > 100 && height < 800) {
- rects.Add(rect);
- }
- }
- }
- return true;
- }, IntPtr.Zero);
- return rects;
- }
- }
-"@
-
- # Check for windows near the center position and calculate offset
- $existingRects = [WindowFinder]::GetVisibleWindowRects()
- $tolerance = 50
-
- foreach ($rect in $existingRects) {
- $windowX = $rect.Left
- $windowY = $rect.Top
-
- # Check if this window is near our intended position (with current offset)
- $targetX = $baseCenterX + $offset
- $targetY = $baseCenterY + $offset
-
- if ([Math]::Abs($windowX - $targetX) -lt $tolerance -and [Math]::Abs($windowY - $targetY) -lt $tolerance) {
- $offset += $offsetStep
- }
- }
-
- # Apply offset (cascade down and right)
- $finalX = $baseCenterX + $offset
- $finalY = $baseCenterY + $offset
-
- # Make sure we stay on screen
- $finalX = [Math]::Min($finalX, $monitorWidth - $form.Width - 10)
- $finalY = [Math]::Min($finalY, $monitorHeight - $form.Height - 10)
- $finalX = [Math]::Max($finalX, 10)
- $finalY = [Math]::Max($finalY, 10)
-
- $form.StartPosition = "Manual"
- $form.Location = New-Object System.Drawing.Point($finalX, $finalY)
-
- # Add message control - use TextBox for scrolling when listening for input
- $marginX = 30
- $marginY = 30
- $labelWidth = $formWidth - ($marginX * 2) - 16 # Account for form border
- $labelHeight = $formHeight - ($marginY * 2) - $totalButtonHeight - 40
-
- # Use a TextBox with scrolling capability
- $textBox = New-Object System.Windows.Forms.TextBox
- $textBox.Location = New-Object System.Drawing.Size($marginX, $marginY)
- $textBox.Size = New-Object System.Drawing.Size($labelWidth, $labelHeight)
- $textBox.Font = New-Object System.Drawing.Font("Segoe UI", 11, [System.Drawing.FontStyle]::Regular)
- $textBox.Text = $message
- $textBox.ForeColor = [System.Drawing.ColorTranslator]::FromHtml($fore)
- $textBox.BackColor = [System.Drawing.ColorTranslator]::FromHtml($back)
- $textBox.Multiline = $true
- $textBox.ReadOnly = $true
- $textBox.ScrollBars = [System.Windows.Forms.ScrollBars]::Vertical
- $textBox.BorderStyle = [System.Windows.Forms.BorderStyle]::None
- $textBox.TabStop = $false
- $form.Controls.Add($textBox)
-
- # Timer to check for message updates from syncHash
- $MessageTimer = New-Object System.Windows.Forms.Timer
- $MessageTimer.Interval = 100
- $MessageTimer.Add_Tick({
- if ($null -ne $syncHash -and $syncHash.Message -ne $textBox.Text) {
- $textBox.Text = $syncHash.Message
- # Auto-scroll to the bottom
- $textBox.SelectionStart = $textBox.Text.Length
- $textBox.ScrollToCaret()
- }
- }.GetNewClosure())
- $MessageTimer.Start()
-
- # Handle form closing via X button
- $form.Add_FormClosing({
- $MessageTimer.Stop()
- $MessageTimer.Dispose()
- $Timer.Stop()
- $Timer.Dispose()
- if ($null -ne $syncHash) {
- # Set result to Cancel or first button if closed via X
- $script:result = if ($null -ne $cancelButtonIndex -and $cancelButtonIndex -lt $buttonList.Count) {
- $buttonList[$cancelButtonIndex]
- } elseif ($buttonList.Count -gt 0) {
- $buttonList[0]
- } else {
- $null
- }
- $syncHash.Result = $script:result
- $syncHash.DialogClosed = $true
- }
- }.GetNewClosure())
-
- # Create buttons (only if there are any)
- if ($hasButtons) {
- $buttonWidth = 90
- $buttonSpacing = 10
- $totalButtonsWidth = ($buttonList.Count * $buttonWidth) + (($buttonList.Count - 1) * $buttonSpacing)
- $startX = ($formWidth - $totalButtonsWidth) / 2
- $buttonY = $formHeight - $buttonHeight - $buttonMargin - 40
-
- for ($i = 0; $i -lt $buttonList.Count; $i++) {
- $button = New-Object System.Windows.Forms.Button
- $button.Text = $buttonList[$i]
- $button.Size = New-Object System.Drawing.Size($buttonWidth, $buttonHeight)
- $button.Location = New-Object System.Drawing.Point(($startX + ($i * ($buttonWidth + $buttonSpacing))), $buttonY)
- $button.BackColor = [System.Drawing.ColorTranslator]::FromHtml($back)
- $button.ForeColor = [System.Drawing.ColorTranslator]::FromHtml($fore)
- $button.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
- $button.FlatAppearance.BorderSize = 1
- $button.FlatAppearance.BorderColor = [System.Drawing.ColorTranslator]::FromHtml($fore)
- $button.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Regular)
-
- # Set as default button if specified
- if ($i -eq $defaultButtonIndex) {
- $form.AcceptButton = $button
- $button.FlatAppearance.BorderSize = 2
- }
-
- # Set as cancel button if specified
- if ($null -ne $cancelButtonIndex -and $i -eq $cancelButtonIndex) {
- $form.CancelButton = $button
- }
-
- # Add click event
- $button.Add_Click({
- $script:result = $this.Text
- $Timer.Stop()
- $Timer.Dispose()
- $MessageTimer.Stop()
- $MessageTimer.Dispose()
- if ($null -ne $syncHash) {
- $syncHash.Result = $script:result
- $syncHash.DialogClosed = $true
- }
- $form.Close()
- }.GetNewClosure())
-
- $form.Controls.Add($button)
- }
- }
-
- # Timer for auto-close
- $Timer.Add_Tick({
- $script:countdown--
- if ($script:countdown -lt 0) {
- $script:result = if ($null -ne $cancelButtonIndex -and $cancelButtonIndex -lt $buttonList.Count) {
- $buttonList[$cancelButtonIndex]
- } else {
- $buttonList[0]
- }
- $Timer.Stop()
- $Timer.Dispose()
- $MessageTimer.Stop()
- $MessageTimer.Dispose()
- if ($null -ne $syncHash) {
- $syncHash.Result = $script:result
- $syncHash.DialogClosed = $true
- }
- $form.Close()
- }
- })
-
- if ($duration -gt 0) {
- $Timer.Start()
- }
-
- # Bring form to front when shown - use Win32 API for reliable foreground activation
- $form.Add_Shown({
- $hwnd = $this.Handle
-
- # Get the foreground window's thread
- $foregroundHwnd = [Win32]::GetForegroundWindow()
- $foregroundThread = [Win32]::GetWindowThreadProcessId($foregroundHwnd, [IntPtr]::Zero)
- $currentThread = [Win32]::GetCurrentThreadId()
-
- # Attach to the foreground thread to allow SetForegroundWindow to work
- if ($foregroundThread -ne $currentThread) {
- [Win32]::AttachThreadInput($currentThread, $foregroundThread, $true) | Out-Null
- }
-
- # Set as topmost, then remove topmost (this forces it to front)
- [Win32]::SetWindowPos($hwnd, [Win32]::HWND_TOPMOST, 0, 0, 0, 0, [Win32]::SWP_NOMOVE -bor [Win32]::SWP_NOSIZE) | Out-Null
- [Win32]::SetWindowPos($hwnd, [Win32]::HWND_NOTOPMOST, 0, 0, 0, 0, [Win32]::SWP_NOMOVE -bor [Win32]::SWP_NOSIZE) | Out-Null
-
- # Show and set foreground
- [Win32]::ShowWindow($hwnd, [Win32]::SW_SHOW) | Out-Null
- [Win32]::SetForegroundWindow($hwnd) | Out-Null
-
- # Detach from the foreground thread
- if ($foregroundThread -ne $currentThread) {
- [Win32]::AttachThreadInput($currentThread, $foregroundThread, $false) | Out-Null
- }
-
- # Also use .NET methods as backup
- $this.Focus()
- $this.Activate()
- $this.BringToFront()
- })
-
- $form.ShowDialog() | Out-Null
-
- return $script:result
-
- }).AddArgument($Message).
- AddArgument($Title).
- AddArgument($Type).
- AddArgument($ButtonList).
- AddArgument($DefaultIndex).
- AddArgument($CancelIndex).
- AddArgument($Duration).
- AddArgument($syncHash)
-
- $PowerShell.Runspace = $runspace
-
- if ($ListenForInput) {
- # Start dialog asynchronously and return syncHash for stdin listening
- $handle = $PowerShell.BeginInvoke()
- return @{
- SyncHash = $syncHash
- PowerShell = $PowerShell
- Handle = $handle
- }
- }
- elseif ($Async) {
- $handle = $PowerShell.BeginInvoke()
-
- $null = Register-ObjectEvent -InputObject $PowerShell -MessageData $handle -EventName InvocationStateChanged -Action {
- param([System.Management.Automation.PowerShell] $ps)
- if ($ps.InvocationStateInfo.State -in 'Completed', 'Failed', 'Stopped') {
- $ps.Runspace.Close()
- $ps.Runspace.Dispose()
- try { $ps.EndInvoke($Event.MessageData) } catch { }
- $ps.Dispose()
- [GC]::Collect()
- }
- }
-
- return $null
- }
- else {
- $result = $PowerShell.Invoke()
- $PowerShell.Runspace.Close()
- $PowerShell.Runspace.Dispose()
- $PowerShell.Dispose()
- return $result
- }
-}
-
-function Show-MacOSDialog {
- param(
- [string]$Message,
- [string]$Title,
- [string]$Type,
- [string[]]$ButtonList,
- [int]$DefaultIndex,
- [int]$CancelIndex
- )
-
- # No buttons - use notification that stays until dismissed (or just display with minimal interaction)
- if ($ButtonList.Count -eq 0) {
- # Use osascript to display a notification - these persist until cleared
- $escapedMessage = $Message -replace '"', '\"'
- $escapedTitle = $Title -replace '"', '\"'
- $appleScript = "display notification `"$escapedMessage`" with title `"$escapedTitle`""
- $appleScript | osascript 2>$null
- # Block indefinitely - caller must kill the process
- while ($true) { Start-Sleep -Seconds 60 }
- return $null
- }
-
- # Map type to AppleScript icon type
- $iconClause = switch ($Type) {
- 'error' { 'as critical' }
- 'warning' { 'as warning' }
- default { '' } # AppleScript doesn't have success/info differentiation
- }
-
- # Build button list for AppleScript
- $buttonClause = "buttons { $($ButtonList -replace '^', '"' -replace '$', '"' -join ', ') }"
- $defaultButtonClause = "default button $(1 + $DefaultIndex)"
-
- $cancelButtonClause = ""
- if ($null -ne $CancelIndex -and $CancelIndex -ne $DefaultIndex) {
- $cancelButtonClause = "cancel button $(1 + $CancelIndex)"
- }
-
- # Escape quotes in message and title
- $escapedMessage = $Message -replace '"', '\"'
- $escapedTitle = $Title -replace '"', '\"'
-
- $appleScript = "display alert `"$escapedTitle`" message `"$escapedMessage`" $iconClause $buttonClause $defaultButtonClause $cancelButtonClause"
-
- # Execute AppleScript
- $result = $appleScript | osascript 2>$null
-
- # Parse result - AppleScript returns "button:" or empty on cancel
- if (-not $result) {
- if ($null -ne $CancelIndex) {
- return $ButtonList[$CancelIndex]
- }
- return $ButtonList[0]
- }
-
- return ($result -replace '.+:')
-}
-
-function Show-LinuxDialog {
- param(
- [string]$Message,
- [string]$Title,
- [string]$Type,
- [string[]]$ButtonList,
- [int]$DefaultIndex,
- [int]$CancelIndex
- )
-
- # No buttons - display message and block indefinitely
- if ($ButtonList.Count -eq 0) {
- $color = switch ($Type) {
- 'error' { 'Red' }
- 'warning' { 'Yellow' }
- 'success' { 'Green' }
- default { 'Cyan' }
- }
- Write-Host ""
- Write-Host "=== $Title ===" -ForegroundColor $color
- Write-Host $Message
- Write-Host "(Press Ctrl+C to dismiss)"
- Write-Host ""
- # Block indefinitely - caller must kill the process
- while ($true) { Start-Sleep -Seconds 60 }
- return $null
- }
-
- # Map type to zenity/kdialog icon
- $zenityType = switch ($Type) {
- 'error' { '--error' }
- 'warning' { '--warning' }
- 'information' { '--info' }
- 'success' { '--info' }
- default { '--info' }
- }
-
- # Try zenity first (GTK)
- $zenityPath = Get-Command zenity -ErrorAction SilentlyContinue
- if ($zenityPath) {
- if ($ButtonList.Count -eq 1) {
- # Simple message with OK
- zenity $zenityType --title="$Title" --text="$Message" 2>$null
- return $ButtonList[0]
- }
- else {
- # Question dialog for multi-button
- $zenityResult = zenity --question --title="$Title" --text="$Message" 2>$null
- if ($LASTEXITCODE -eq 0) {
- return $ButtonList[0] # "Yes" or first button
- }
- else {
- return $ButtonList[1] # "No" or second button
- }
- }
- }
-
- # Try kdialog (KDE)
- $kdialogPath = Get-Command kdialog -ErrorAction SilentlyContinue
- if ($kdialogPath) {
- $kdType = switch ($Type) {
- 'error' { '--error' }
- 'warning' { '--sorry' }
- default { '--msgbox' }
- }
-
- if ($ButtonList.Count -eq 1) {
- kdialog $kdType "$Message" --title "$Title" 2>$null
- return $ButtonList[0]
- }
- else {
- $kdResult = kdialog --yesno "$Message" --title "$Title" 2>$null
- if ($LASTEXITCODE -eq 0) {
- return $ButtonList[0]
- }
- else {
- return $ButtonList[1]
- }
- }
- }
-
- # Fallback to console
- Write-Host ""
- Write-Host "=== $Title ===" -ForegroundColor $(switch ($Type) {
- 'error' { 'Red' }
- 'warning' { 'Yellow' }
- 'success' { 'Green' }
- default { 'Cyan' }
- })
- Write-Host $Message
- Write-Host ""
-
- if ($ButtonList.Count -eq 1) {
- Read-Host "Press Enter to continue"
- return $ButtonList[0]
- }
-
- # Show options for multi-button
- for ($i = 0; $i -lt $ButtonList.Count; $i++) {
- $prefix = if ($i -eq $DefaultIndex) { "*" } else { " " }
- Write-Host "$prefix[$($i + 1)] $($ButtonList[$i])"
- }
-
- $defaultDisplay = $DefaultIndex + 1
- $choice = Read-Host "Enter choice (1-$($ButtonList.Count)) [default: $defaultDisplay]"
-
- if ([string]::IsNullOrWhiteSpace($choice)) {
- return $ButtonList[$DefaultIndex]
- }
-
- $choiceNum = 0
- if ([int]::TryParse($choice, [ref]$choiceNum) -and $choiceNum -ge 1 -and $choiceNum -le $ButtonList.Count) {
- return $ButtonList[$choiceNum - 1]
- }
-
- return $ButtonList[$DefaultIndex]
-}
-
-# Main execution
-# Allow $IsLinux and $IsMacOS to be accessed safely in Windows PowerShell
-Set-StrictMode -Off
-
-$config = $buttonMap[$Buttons]
-$buttonList = $config.buttonList
-$defaultIndex = if ($DefaultButtonIndex -ge 0) { $DefaultButtonIndex } else { $config.defaultButtonIndex }
-$cancelIndex = $config.cancelButtonIndex
-
-# Ensure default index is within bounds
-$defaultIndex = [math]::Min($buttonList.Count - 1, $defaultIndex)
-
-if ($IsLinux) {
- $result = Show-LinuxDialog -Message $Message -Title $Title -Type $Type -ButtonList $buttonList -DefaultIndex $defaultIndex -CancelIndex $cancelIndex
-}
-elseif ($IsMacOS) {
- $result = Show-MacOSDialog -Message $Message -Title $Title -Type $Type -ButtonList $buttonList -DefaultIndex $defaultIndex -CancelIndex $cancelIndex
-}
-else {
- # Windows
- if ($ListenForInput) {
- # Start dialog and listen for stdin input to append to message
- $dialogInfo = Show-WindowsDialog -Message $Message -Title $Title -Type $Type -ButtonList $buttonList -DefaultIndex $defaultIndex -CancelIndex $cancelIndex -Duration $Duration -Async $false -ListenForInput $true
-
- $syncHash = $dialogInfo.SyncHash
- $ps = $dialogInfo.PowerShell
- $handle = $dialogInfo.Handle
-
- try {
- # Read from stdin and append to message until dialog closes or EOF
- # Use a background runspace to read stdin without blocking the main thread
- $stdinRunspace = [runspacefactory]::CreateRunspace()
- $stdinRunspace.Open()
- $stdinRunspace.SessionStateProxy.SetVariable('syncHash', $syncHash)
-
- $stdinPS = [PowerShell]::Create().AddScript({
- param($syncHash)
- $stdinStream = [System.Console]::OpenStandardInput()
- $reader = New-Object System.IO.StreamReader($stdinStream)
-
- try {
- while (-not $syncHash.DialogClosed) {
- $line = $reader.ReadLine()
- if ($null -eq $line) {
- # EOF reached
- break
- }
- # Append line to message (use CRLF for Windows TextBox)
- $syncHash.Message = $syncHash.Message + "`r`n" + $line
- }
- }
- finally {
- $reader.Dispose()
- $stdinStream.Dispose()
- }
- }).AddArgument($syncHash)
-
- $stdinPS.Runspace = $stdinRunspace
- $stdinHandle = $stdinPS.BeginInvoke()
-
- # Wait for dialog to close
- while (-not $syncHash.DialogClosed) {
- Start-Sleep -Milliseconds 100
- }
-
- # Clean up stdin reader
- if (-not $stdinHandle.IsCompleted) {
- $stdinPS.Stop()
- }
- $stdinRunspace.Close()
- $stdinRunspace.Dispose()
- $stdinPS.Dispose()
- }
- finally {
- # Wait for dialog to complete if still running
- if (-not $handle.IsCompleted) {
- $null = $ps.EndInvoke($handle)
- }
- $ps.Runspace.Close()
- $ps.Runspace.Dispose()
- $ps.Dispose()
- }
-
- $result = $syncHash.Result
- }
- else {
- $result = Show-WindowsDialog -Message $Message -Title $Title -Type $Type -ButtonList $buttonList -DefaultIndex $defaultIndex -CancelIndex $cancelIndex -Duration $Duration -Async $Async -ListenForInput $false
- }
-}
-
-return $result
diff --git a/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/ProcessHelper.cs b/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/ProcessHelper.cs
index e96a1822f..5b03afc2f 100644
--- a/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/ProcessHelper.cs
+++ b/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/ProcessHelper.cs
@@ -1,6 +1,9 @@
using CliWrap;
using CliWrap.EventStream;
using Microsoft.CodeAnalysis;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
@@ -20,17 +23,34 @@ public static class ProcessHelper
/// The name of the PowerShell script file to execute.
/// Command-line arguments to pass to the script.
/// A StringBuilder to accumulate log output.
- /// A cancellation token to cancel the operation.
+ /// The SourceProductionContext for diagnostic reporting.
/// Optional environment variables to set for the process.
public static async Task RunPowerShellScript(string processName, string workingDirectory,
- string powershellScriptName, string arguments, StringBuilder logBuilder, CancellationToken token,
+ string powershellScriptName, string[] arguments, StringBuilder logBuilder, SourceProductionContext context,
Dictionary? environmentVariables = null)
{
- // Since we are always providing the scripts, this is safe to call `ByPass`
- string shellArguments = $"-NoProfile -ExecutionPolicy ByPass -File \"{
- Path.Combine(workingDirectory, powershellScriptName)}\" {arguments}";
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ arguments =
+ [
+ "-NoProfile",
+ "-ExecutionPolicy",
+ "ByPass",
+ "-File",
+ Path.Combine(workingDirectory, powershellScriptName),
+ ..arguments
+ ];
+ }
+ else
+ {
+ arguments =
+ [
+ Path.Combine(workingDirectory, powershellScriptName),
+ ..arguments
+ ];
+ }
- await Execute(processName, workingDirectory, "pwsh", shellArguments, logBuilder, token,
+ await Execute(processName, workingDirectory, "pwsh", arguments, logBuilder, context,
environmentVariables);
}
@@ -41,15 +61,27 @@ await Execute(processName, workingDirectory, "pwsh", shellArguments, logBuilder,
/// The working directory for the command execution.
/// The PowerShell command to execute.
/// A StringBuilder to accumulate log output.
- /// A cancellation token to cancel the operation.
+ /// The SourceProductionContext for diagnostic reporting.
/// Optional environment variables to set for the process.
public static async Task RunPowerShellCommand(string processName, string workingDirectory,
- string arguments, StringBuilder logBuilder, CancellationToken token,
+ string[] arguments, StringBuilder logBuilder, SourceProductionContext context,
Dictionary? environmentVariables = null)
{
- string shellArguments = $"-NoProfile -ExecutionPolicy ByPass -Command {{ {arguments} }}";
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ arguments =
+ [
+ "-NoProfile",
+ "-ExecutionPolicy",
+ "ByPass",
+ "-Command",
+ "{",
+ ..arguments,
+ "}"
+ ];
+ }
- await Execute(processName, workingDirectory, "pwsh", shellArguments, logBuilder, token,
+ await Execute(processName, workingDirectory, "pwsh", arguments, logBuilder, context,
environmentVariables);
}
@@ -61,11 +93,11 @@ await Execute(processName, workingDirectory, "pwsh", shellArguments, logBuilder,
/// The executable file name. If null, uses the platform-specific shell command.
/// Command-line arguments to pass to the process.
/// A StringBuilder to accumulate log output.
- /// A cancellation token to cancel the operation.
+ /// The SourceProductionContext for diagnostic reporting.
/// Optional environment variables to set for the process.
/// Thrown when the process exits with a non-zero exit code.
public static async Task Execute(string processName, string workingDirectory, string? fileName,
- string shellArguments, StringBuilder logBuilder, CancellationToken token,
+ string[] shellArguments, StringBuilder logBuilder, SourceProductionContext context,
Dictionary? environmentVariables = null)
{
fileName ??= shellCommand;
@@ -74,7 +106,7 @@ public static async Task Execute(string processName, string workingDirectory, st
int? processId = null;
int? exitCode = null;
- token.Register(() =>
+ context.CancellationToken.Register(() =>
{
logBuilder.AppendLine($"{processName}: Command execution cancelled.");
logBuilder.AppendLine(outputBuilder.ToString());
@@ -87,31 +119,31 @@ public static async Task Execute(string processName, string workingDirectory, st
.WithValidation(CommandResultValidation.None)
.WithEnvironmentVariables(environmentVariables ?? new Dictionary());
- await foreach (CommandEvent cmdEvent in cmd.ListenAsync(cancellationToken: token))
+ await foreach (var cmdEvent in cmd.ListenAsync(context.CancellationToken))
{
switch (cmdEvent)
{
case StartedCommandEvent started:
processId = started.ProcessId;
- outputBuilder.AppendLine($"{processName} Process started: {started.ProcessId}");
+ outputBuilder.AppendLine($" - {processName} Process started: {started.ProcessId}");
- outputBuilder.AppendLine($"{processName} - PID {processId}: Executing command: {fileName} {
- shellArguments}");
+ outputBuilder.AppendLine($" - {processName} - PID {processId}: Executing command: {fileName} {
+ string.Join(" ", shellArguments)}");
break;
case StandardOutputCommandEvent stdOut:
string line = stdOut.Text.Trim();
- outputBuilder.AppendLine($"{processName} - PID {processId}: [stdout] {line}");
+ outputBuilder.AppendLine($" - {processName} - PID {processId}: [stdout] {line}");
break;
case StandardErrorCommandEvent stdErr:
- outputBuilder.AppendLine($"{processName} - PID {processId}: [stderr] {stdErr.Text}");
+ outputBuilder.AppendLine($" - {processName} - PID {processId}: [stderr] {stdErr.Text}");
break;
case ExitedCommandEvent exited:
exitCode = exited.ExitCode;
- outputBuilder.AppendLine($"{processName} - PID {processId}: Process exited with code: {
+ outputBuilder.AppendLine($" - {processName} - PID {processId}: Process exited with code: {
exited.ExitCode}");
break;
@@ -126,12 +158,48 @@ public static async Task Execute(string processName, string workingDirectory, st
if (exitCode != 0)
{
- throw new ProcessException($"{processName}: Error executing command '{shellArguments}' for process {
- processId}. Exit code: {exitCode}");
+ var response = logBuilder.ToString();
+ Log(processName, response, DiagnosticSeverity.Info, context);
+
+ if (response.Contains("The process cannot access the file") && (fileName == "dotnet"))
+ {
+ var programName = shellArguments[1]; // dotnet[fileName] run[arg[0]] ESBuild.cs[arg[1]]
+
+ var runningProc = Process.GetProcessesByName("dotnet")
+ .FirstOrDefault(p => p.MainModule?.FileName.Contains(programName) ?? false);
+
+ if (runningProc is not null)
+ {
+ try
+ {
+ runningProc.Kill();
+ runningProc.WaitForExit();
+ }
+ catch
+ {
+ // ignore
+ }
+ }
+
+ await Task.Delay(500);
+
+ await Execute(processName, workingDirectory, fileName, shellArguments, logBuilder, context,
+ environmentVariables);
+
+ return;
+ }
+
+ Log(processName,
+ $"Command '{fileName} {string.Join(" ", shellArguments)}' failed with exit code {exitCode}.",
+ DiagnosticSeverity.Error,
+ context);
+
+ return;
}
// Return the standard output if the process completed normally
- logBuilder.AppendLine($"{processName}: Command '{shellArguments}' completed successfully on process {processId
+ logBuilder.AppendLine($" - {processName}: Command '{string.Join(" ", shellArguments)
+ }' completed successfully on process {processId
}.");
}
@@ -142,9 +210,16 @@ public static async Task Execute(string processName, string workingDirectory, st
/// The diagnostic message content.
/// The severity level of the diagnostic.
/// The source production context to report the diagnostic to.
+ /// Whether to show a popup console window with the message
+ /// Optional session ID to identify the console dialog instance. Each unique session ID gets its own dialog window.
public static void Log(string title, string message, DiagnosticSeverity severity,
- SourceProductionContext context)
+ SourceProductionContext context, bool showConsole = false, string? sessionId = null)
{
+ if (showConsole)
+ {
+ ShowOrUpdateConsole(title, message, sessionId);
+ }
+
context.ReportDiagnostic(Diagnostic.Create(new DiagnosticDescriptor("GBSourceGen",
title,
message,
@@ -153,10 +228,156 @@ public static void Log(string title, string message, DiagnosticSeverity severity
isEnabledByDefault: true), Location.None));
}
+ ///
+ /// Closes the console window for the specified session.
+ ///
+ /// The session ID of the console dialog to close.
+ public static void CloseDialog(string sessionId)
+ {
+ _ = Task.Run(() =>
+ {
+ if (!_consoleProcesses.TryRemove(sessionId, out var process))
+ {
+ return;
+ }
+
+ if (HasProcessExited(process))
+ {
+ return;
+ }
+
+ try
+ {
+ process.StandardInput.Flush();
+ Thread.Sleep(500);
+ process.StandardInput.WriteLine("exit");
+ process.WaitForExit();
+ process.Dispose();
+ }
+ catch (InvalidOperationException)
+ {
+ // Process was not started or has already exited - ignore
+ }
+ });
+ }
+
+ ///
+ /// Closes all open console windows created by .
+ ///
+ public static void CloseAllDialogs()
+ {
+ foreach (var sessionId in _consoleProcesses.Keys.ToArray())
+ {
+ CloseDialog(sessionId);
+ }
+ }
+
+ private static void ShowOrUpdateConsole(string title, string message, string? sessionId = null,
+ [CallerFilePath] string callerFilePath = "")
+ {
+ // Use session ID if provided, otherwise use title as the key
+ var key = sessionId ?? title;
+
+ try
+ {
+ // Try to get existing process for this session
+ if (_consoleProcesses.TryGetValue(key, out var existingProcess) && !HasProcessExited(existingProcess))
+ {
+ existingProcess.StandardInput.WriteLine(message);
+
+ return;
+ }
+
+ // Need to create a new process - use lock to prevent race conditions
+ lock (_consoleLock)
+ {
+ // Double-check after acquiring lock
+ if (_consoleProcesses.TryGetValue(key, out existingProcess) && !HasProcessExited(existingProcess))
+ {
+ existingProcess.StandardInput.WriteLine(message);
+
+ return;
+ }
+
+ // Remove stale process if it exists
+ if (existingProcess is not null)
+ {
+ _consoleProcesses.TryRemove(key, out _);
+
+ try
+ {
+ existingProcess.Dispose();
+ }
+ catch
+ {
+ // ignore disposal errors
+ }
+ }
+
+ var buildScriptPath = Path.GetFullPath(Path.Combine(
+ Path.GetDirectoryName(
+ callerFilePath)!, // GeoBlazor/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared
+ "..", // GeoBlazor/src
+ "..", // GeoBlazor Core repo root
+ "build-tools"));
+
+ string[] args =
+ [
+ "ConsoleDialog.dll",
+ $"\"{title}\"",
+ "-w",
+ "2"
+ ];
+
+ ProcessStartInfo startInfo = new("dotnet")
+ {
+ Arguments = string.Join(" ", args),
+ WorkingDirectory = buildScriptPath,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ CreateNoWindow = true
+ };
+
+ var newProcess = Process.Start(startInfo);
+
+ if (newProcess is null)
+ {
+ return; // Failed to start process
+ }
+
+ newProcess.StandardInput.AutoFlush = true;
+ _consoleProcesses[key] = newProcess;
+ newProcess.StandardInput.WriteLine(message);
+ }
+ }
+ catch (InvalidOperationException)
+ {
+ // Process failed to start or is in invalid state - remove from dictionary
+ _consoleProcesses.TryRemove(key, out _);
+ }
+ }
+
+ private static bool HasProcessExited(Process process)
+ {
+ try
+ {
+ return process.HasExited;
+ }
+ catch (InvalidOperationException)
+ {
+ return true; // Process was never started or is in invalid state
+ }
+ }
+
private static readonly string shellCommand = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? WindowsShell
: LinuxShell;
+ private static readonly ConcurrentDictionary _consoleProcesses = new();
+ private static readonly object _consoleLock = new();
+
private const string LinuxShell = "/bin/bash";
private const string WindowsShell = "cmd";
}
diff --git a/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/ProtobufDefinitionsGenerator.cs b/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/ProtobufDefinitionsGenerator.cs
index 2f5ca8b3d..76b3318dd 100644
--- a/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/ProtobufDefinitionsGenerator.cs
+++ b/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/ProtobufDefinitionsGenerator.cs
@@ -13,15 +13,15 @@ namespace dymaptic.GeoBlazor.Core.SourceGenerator.Shared;
public static class ProtobufDefinitionsGenerator
{
public static Dictionary UpdateProtobufDefinitions(SourceProductionContext context,
- ImmutableArray types, string corePath)
+ ImmutableArray types, string corePath, bool showDialog, string? sessionId = null)
{
ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
"Updating Protobuf definitions...",
DiagnosticSeverity.Info,
- context);
+ context, showDialog, sessionId);
// fetch protobuf definitions
- var protoTypeContent = Generate(context, types);
+ var protoTypeContent = Generate(context, types, showDialog, sessionId);
var typescriptContent = $"""
export let protoTypeDefinitions: string = `
@@ -44,65 +44,27 @@ public static Dictionary UpdateProtobufDefinitio
// must use GetAwaiter().GetResult(), since Source Generator is not Async
ProcessHelper.RunPowerShellScript("Copy Protobuf Definitions",
corePath, scriptPath,
- $"-Content \"{encoded}\"",
- logBuilder, context.CancellationToken)
+ ["-Content", encoded],
+ logBuilder, context)
.GetAwaiter()
.GetResult();
ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
logBuilder.ToString(),
DiagnosticSeverity.Info,
- context);
+ context, sessionId: sessionId);
ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
"Protobuf definitions updated successfully.",
DiagnosticSeverity.Info,
- context);
+ context, showDialog, sessionId);
return _protoDefinitions ?? [];
}
- private static string Generate(SourceProductionContext context,
- ImmutableArray types)
- {
- try
- {
- ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
- "Generating Protobuf schema",
- DiagnosticSeverity.Info,
- context);
-
- // Extract protobuf definitions from syntax nodes
- _protoDefinitions ??= ExtractProtobufDefinitions(types, context);
-
- ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
- $"Extracted {_protoDefinitions.Count} Protobuf message definitions.",
- DiagnosticSeverity.Info,
- context);
-
- // Generate new proto file content
- var newProtoContent = GenerateProtoFileContent(_protoDefinitions);
-
- ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
- "Protobuf schema generation complete",
- DiagnosticSeverity.Info,
- context);
-
- return newProtoContent;
- }
- catch (Exception ex)
- {
- ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
- $"Error generating Protobuf definitions: {ex.Message}",
- DiagnosticSeverity.Error,
- context);
-
- return string.Empty;
- }
- }
-
- private static Dictionary ExtractProtobufDefinitions(
- ImmutableArray types, SourceProductionContext context)
+ public static Dictionary ExtractProtobufDefinitions(
+ ImmutableArray types, SourceProductionContext context, bool showDialog,
+ string? sessionId = null)
{
var definitions = new Dictionary();
const string protoContractAttribute = "ProtoContract";
@@ -123,7 +85,7 @@ private static Dictionary ExtractProtobufDefinit
type.AttributeLists.SelectMany(al => al.Attributes.SelectMany(a => a.ToString())))
}",
DiagnosticSeverity.Warning,
- context);
+ context, showDialog, sessionId);
}
continue;
@@ -143,13 +105,52 @@ private static Dictionary ExtractProtobufDefinit
ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
$"Error processing syntax node {type.Identifier.Text}: {ex.Message}",
DiagnosticSeverity.Warning,
- context);
+ context, showDialog, sessionId);
}
}
return definitions;
}
+ private static string Generate(SourceProductionContext context,
+ ImmutableArray types, bool showDialog, string? sessionId = null)
+ {
+ try
+ {
+ ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
+ "Generating Protobuf schema",
+ DiagnosticSeverity.Info,
+ context, showDialog, sessionId);
+
+ // Extract protobuf definitions from syntax nodes
+ _protoDefinitions ??= ExtractProtobufDefinitions(types, context, showDialog, sessionId);
+
+ ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
+ $"Extracted {_protoDefinitions.Count} Protobuf message definitions.",
+ DiagnosticSeverity.Info,
+ context, showDialog, sessionId);
+
+ // Generate new proto file content
+ var newProtoContent = GenerateProtoFileContent(_protoDefinitions);
+
+ ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
+ "Protobuf schema generation complete",
+ DiagnosticSeverity.Info,
+ context, showDialog, sessionId);
+
+ return newProtoContent;
+ }
+ catch (Exception ex)
+ {
+ ProcessHelper.Log(nameof(ProtobufDefinitionsGenerator),
+ $"Error generating Protobuf definitions: {ex.Message}",
+ DiagnosticSeverity.Error,
+ context, showDialog, sessionId);
+
+ return string.Empty;
+ }
+ }
+
private static ProtoMessageDefinition? ExtractMessageDefinition(BaseTypeDeclarationSyntax syntaxNode)
{
// Get ProtoContract attribute to find the message name
diff --git a/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/SerializationGenerator.cs b/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/SerializationGenerator.cs
index 4a291c4ea..27d92c4d0 100644
--- a/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/SerializationGenerator.cs
+++ b/src/dymaptic.GeoBlazor.Core.SourceGenerator.Shared/SerializationGenerator.cs
@@ -18,19 +18,15 @@ public static class SerializationGenerator
/// The collection of type declarations to analyze for serialization attributes.
/// A dictionary of Protobuf message definitions keyed by type name.
/// Whether generating for Pro (true) or Core (false) library.
- /// If true, skips file generation (for testing purposes).
+ /// Whether to show progress dialog during generation.
+ /// Optional session ID to identify the console dialog instance.
public static void GenerateSerializationDataClass(SourceProductionContext context,
ImmutableArray types,
Dictionary protoMessageDefinitions,
- bool isPro, bool isTest)
+ bool isPro, bool showDialog, string? sessionId = null)
{
try
{
- ProcessHelper.Log(nameof(SerializationGenerator),
- "Generating serialized data class...",
- DiagnosticSeverity.Info,
- context);
-
ImmutableArray serializedMethodsCollection =
[
..types
@@ -89,7 +85,7 @@ namespace dymaptic.GeoBlazor.{{(isPro ? "Pro" : "Core")}}.Serialization;
///
/// This class is generated by a source generator and contains pre-analyzed serialization information.
///
- internal static class {{className}}
+ internal static partial class {{className}}
{
""");
@@ -106,26 +102,16 @@ internal static class {{className}}
ProcessHelper.Log(nameof(SerializationGenerator),
$"Generated serialized data class: {className}.g.cs",
DiagnosticSeverity.Info,
- context);
+ context, showDialog, sessionId);
- if (isTest)
- {
- ProcessHelper.Log(nameof(SerializationGenerator),
- $"Skipping generating file for test.",
- DiagnosticSeverity.Info,
- context);
- }
- else
- {
- context.AddSource($"{className}.g.cs", classBuilder.ToString());
- }
+ context.AddSource($"{className}.g.cs", classBuilder.ToString());
}
catch (Exception ex)
{
ProcessHelper.Log(nameof(SerializationGenerator),
$"Error generating serialized data class: {ex}",
DiagnosticSeverity.Error,
- context);
+ context, showDialog, sessionId);
}
}
@@ -173,7 +159,7 @@ private static string GenerateExtensionMethods(Dictionary
/// A collection of types that can be serialized to Protobuf
///
- public static Dictionary ProtoContractTypes => _protoContractTypes;
+ public static partial Dictionary ProtoContractTypes => _protoContractTypes;
private static readonly Dictionary _protoContractTypes = new()
{
@@ -184,7 +170,7 @@ private static string GenerateExtensionMethods(Dictionary
/// A collection of types that can be serialized to Protobuf as collections of a specific Type
///
- public static Dictionary ProtoCollectionTypes => _protoCollectionTypes;
+ public static partial Dictionary ProtoCollectionTypes => _protoCollectionTypes;
private static readonly Dictionary _protoCollectionTypes = new()
{
@@ -381,7 +367,7 @@ private static string GenerateSerializableMethodRecords(
///
/// A collection of serializable methods and their parameters/return types.
///
- public static Dictionary SerializableMethods => _serializableMethods
+ public static partial Dictionary SerializableMethods => _serializableMethods
.Concat(CoreSerializationData.SerializableMethods)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
@@ -396,7 +382,7 @@ private static string GenerateSerializableMethodRecords(
///
/// A collection of serializable methods and their parameters/return types.
///
- public static Dictionary SerializableMethods => _serializableMethods;
+ public static partial Dictionary SerializableMethods => _serializableMethods;
private static readonly Dictionary _serializableMethods = new()
{
diff --git a/src/dymaptic.GeoBlazor.Core.SourceGenerator/ESBuildGenerator.cs b/src/dymaptic.GeoBlazor.Core.SourceGenerator/ESBuildGenerator.cs
index a8ab6256e..ea8489806 100644
--- a/src/dymaptic.GeoBlazor.Core.SourceGenerator/ESBuildGenerator.cs
+++ b/src/dymaptic.GeoBlazor.Core.SourceGenerator/ESBuildGenerator.cs
@@ -14,10 +14,9 @@ namespace dymaptic.GeoBlazor.Core.SourceGenerator;
[SuppressMessage("MicrosoftCodeAnalysisCorrectness", "RS1035:Do not use APIs banned for analyzers")]
public class ESBuildGenerator : IIncrementalGenerator
{
- ///
- /// Gets a value indicating whether an ESBuild process is currently running.
- ///
- public static bool InProcess { get; private set; }
+ private static string? BuildToolsPath => _corePath is null
+ ? null
+ : Path.GetFullPath(Path.Combine(_corePath, "..", "..", "build-tools"));
///
public void Initialize(IncrementalGeneratorInitializationContext context)
@@ -30,7 +29,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
.Collect();
// Reads the MSBuild properties to get the project directory and configuration.
- IncrementalValueProvider<(string?, string?, string?)> optionsProvider =
+ IncrementalValueProvider<(string?, string?, string?, string?)> optionsProvider =
context.AnalyzerConfigOptionsProvider.Select((configProvider, _) =>
{
configProvider.GlobalOptions.TryGetValue("build_property.CoreProjectPath",
@@ -42,24 +41,25 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
configProvider.GlobalOptions.TryGetValue("build_property.PipelineBuild",
out string? pipelineBuild);
- return (projectDirectory, configuration, pipelineBuild);
+ configProvider.GlobalOptions.TryGetValue("build_property.DesignTimeBuild",
+ out var designTimeBuild);
+
+ return (projectDirectory, configuration, pipelineBuild, designTimeBuild);
});
- IncrementalValueProvider<((ImmutableArray Left, (string?, string?, string?) Right) Left,
- Compilation Right)> combined =
- tsFilesProvider
- .Combine(optionsProvider)
- .Combine(context.CompilationProvider);
+ var
+ combined =
+ tsFilesProvider.Combine(optionsProvider);
context.RegisterSourceOutput(combined, FilesChanged);
}
private void FilesChanged(SourceProductionContext context,
- ((ImmutableArray Files,
- (string? ProjectDirectory, string? Configuration, string? PipelineBuild) Options) Data,
- Compilation Compilation) pipeline)
+ (ImmutableArray Files,
+ (string? ProjectDirectory, string? Configuration, string? PipelineBuild, string? DesignTimeBuild) Options)
+ pipeline)
{
- if (!SetProjectDirectoryAndConfiguration(pipeline.Data.Options, context))
+ if (!SetProjectDirectoryAndConfiguration(pipeline.Options, context))
{
return;
}
@@ -69,7 +69,7 @@ private void FilesChanged(SourceProductionContext context,
DiagnosticSeverity.Info,
context);
- if (pipeline.Data.Options.PipelineBuild == "true")
+ if (pipeline.Options.PipelineBuild == "true")
{
// If the pipeline build is enabled, we skip the ESBuild process.
// This is to avoid race conditions where the files are not ready on time, and we do the build separately.
@@ -81,14 +81,14 @@ private void FilesChanged(SourceProductionContext context,
return;
}
- if (pipeline.Data.Files.Length > 0)
+ if (pipeline.Files.Length > 0)
{
LaunchESBuild(context);
}
}
private bool SetProjectDirectoryAndConfiguration(
- (string? ProjectDirectory, string? Configuration, string? _) options,
+ (string? ProjectDirectory, string? Configuration, string? _, string? DesignTimeBuild) options,
SourceProductionContext context)
{
string? projectDirectory = options.ProjectDirectory;
@@ -130,6 +130,7 @@ private bool SetProjectDirectoryAndConfiguration(
if (options.Configuration is { } configuration)
{
_configuration = configuration;
+ _isDesignTimeBuild = options.DesignTimeBuild == "true";
return true;
}
@@ -152,6 +153,7 @@ private void LaunchESBuild(SourceProductionContext context)
context);
StringBuilder logBuilder = new StringBuilder(DateTime.Now.ToLongTimeString());
+ logBuilder.AppendLine();
logBuilder.AppendLine("Starting Core ESBuild process...");
try
@@ -160,12 +162,25 @@ private void LaunchESBuild(SourceProductionContext context)
bool buildSuccess = false;
bool proBuildSuccess = false;
- // gets the esBuild.ps1 script from the Core path
+ // gets the ESBuild.cs script
+ // Only show dialog on full compilation builds, not design-time builds
+ string[] coreArgs =
+ [
+ "ESBuild.dll",
+ "-c", _configuration!, // set config for ESBuild
+ "-d" // show dialog
+ ];
+
+ if (!_isDesignTimeBuild)
+ {
+ coreArgs = [..coreArgs, "-v"]; // show verbose output
+ }
+
tasks.Add(Task.Run(async () =>
{
- await ProcessHelper.RunPowerShellScript("Core",
- _corePath!, "esBuild.ps1",
- $"-c {_configuration}", logBuilder, context.CancellationToken);
+ await ProcessHelper.Execute("Core",
+ BuildToolsPath!, "dotnet",
+ coreArgs, logBuilder, context);
buildSuccess = true;
}));
@@ -173,11 +188,24 @@ await ProcessHelper.RunPowerShellScript("Core",
{
logBuilder.AppendLine("Starting Pro ESBuild process...");
+ string[] proArgs =
+ [
+ "ESBuild.dll",
+ "-c", _configuration!, // set config for ESBuild
+ "-d", // show dialog
+ "--pro" // build for Pro project
+ ];
+
+ if (!_isDesignTimeBuild)
+ {
+ proArgs = [..proArgs, "-v"]; // show verbose output
+ }
+
tasks.Add(Task.Run(async () =>
{
- await ProcessHelper.RunPowerShellScript("Pro",
- _proPath, "esProBuild.ps1",
- $"-c {_configuration}", logBuilder, context.CancellationToken);
+ await ProcessHelper.Execute("Pro",
+ BuildToolsPath!, "dotnet",
+ proArgs, logBuilder, context);
proBuildSuccess = true;
}));
}
@@ -232,11 +260,11 @@ await ProcessHelper.RunPowerShellScript("Pro",
private void ClearESBuildLocks(SourceProductionContext context)
{
StringBuilder logBuilder = new();
- string rootCorePath = Path.Combine(_corePath!, "..", "..");
- _ = Task.Run(async () => await ProcessHelper.RunPowerShellScript("Clear Locks",
- rootCorePath, "esBuildClearLocks.ps1", "",
- logBuilder, context.CancellationToken));
+ _ = Task.Run(async () => await ProcessHelper.Execute("Clear Locks",
+ BuildToolsPath!, "dotnet",
+ ["ESBuildClearLocks.dll"],
+ logBuilder, context));
ProcessHelper.Log(nameof(ESBuildGenerator),
"Cleared ESBuild Process Locks",
@@ -247,4 +275,5 @@ private void ClearESBuildLocks(SourceProductionContext context)
private static string? _corePath;
private static string? _proPath;
private static string? _configuration;
+ private static bool _isDesignTimeBuild;
}
\ No newline at end of file
diff --git a/src/dymaptic.GeoBlazor.Core.SourceGenerator/Properties/launchSettings.json b/src/dymaptic.GeoBlazor.Core.SourceGenerator/Properties/launchSettings.json
new file mode 100644
index 000000000..bfb3c206b
--- /dev/null
+++ b/src/dymaptic.GeoBlazor.Core.SourceGenerator/Properties/launchSettings.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "Generators": {
+ "commandName": "DebugRoslynComponent",
+ "targetProject": "../../test/dymaptic.GeoBlazor.Core.SourceGenerator.Tests/dymaptic.GeoBlazor.Core.SourceGenerator.Tests.csproj"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/dymaptic.GeoBlazor.Core.SourceGenerator/ProtobufSourceGenerator.cs b/src/dymaptic.GeoBlazor.Core.SourceGenerator/ProtobufSourceGenerator.cs
index 3f5c9033d..c1c6e068c 100644
--- a/src/dymaptic.GeoBlazor.Core.SourceGenerator/ProtobufSourceGenerator.cs
+++ b/src/dymaptic.GeoBlazor.Core.SourceGenerator/ProtobufSourceGenerator.cs
@@ -32,60 +32,74 @@ syntaxNode is ClassDeclarationSyntax or StructDeclarationSyntax or RecordDeclara
.Collect();
// Reads the MSBuild properties to get the project directory.
- IncrementalValueProvider optionsProvider =
+ IncrementalValueProvider<(string?, string?)> optionsProvider =
context.AnalyzerConfigOptionsProvider.Select((configProvider, _) =>
{
configProvider.GlobalOptions.TryGetValue("build_property.CoreProjectPath",
out var projectDirectory);
- return projectDirectory;
+ configProvider.GlobalOptions.TryGetValue("build_property.PipelineBuild",
+ out var pipelineBuild);
+
+ return (projectDirectory, pipelineBuild);
});
- var combined =
- typeProvider.Combine(optionsProvider)
- .Combine(context.CompilationProvider);
+ IncrementalValueProvider<(ImmutableArray Left, (string?, string?) Right)> combined =
+ typeProvider.Combine(optionsProvider);
context.RegisterSourceOutput(combined, FilesChanged);
}
private void FilesChanged(SourceProductionContext context,
- ((ImmutableArray Types, string? ProjectDirectory) Data,
- Compilation Compilation) pipeline)
+ (ImmutableArray Types, (string? ProjectDirectory, string? PipelineBuild) Options)
+ pipeline)
{
- // Skip if not running from the Core project
- if (pipeline.Compilation.AssemblyName != "dymaptic.GeoBlazor.Core")
- {
- return;
- }
+ _corePath = pipeline.Options.ProjectDirectory;
+ var showDialog = pipeline.Options.PipelineBuild != "true";
- // Skip source generation if the project path is not available
- if (string.IsNullOrEmpty(pipeline.Data.ProjectDirectory))
+ // Generate a unique session ID for this build session
+ var sessionId = $"{nameof(ProtobufSourceGenerator)}_{Guid.NewGuid():N}";
+
+ if (pipeline.Types.Length > 0)
{
- ProcessHelper.Log(nameof(ProtobufSourceGenerator),
- "CoreProjectPath not set. Skipping protobuf source generation.",
- DiagnosticSeverity.Warning,
- context);
+ try
+ {
+ ProcessHelper.Log(nameof(ProtobufSourceGenerator),
+ $"Source Generation triggered with {pipeline.Types.Length} protobuf types found.",
+ DiagnosticSeverity.Info,
+ context, showDialog, sessionId);
- return;
- }
+ var protoDefinitions = ProtobufDefinitionsGenerator
+ .UpdateProtobufDefinitions(context, pipeline.Types, _corePath!, showDialog, sessionId);
- // Log that protobuf types were found (infrastructure ready for future implementation)
- if (pipeline.Data.Types.Length > 0)
- {
- ProcessHelper.Log(nameof(ProtobufSourceGenerator),
- $"Found {pipeline.Data.Types.Length} protobuf-serializable types.",
- DiagnosticSeverity.Info,
- context);
-
- // TODO: Generate protobuf serialization records and registration code.
- // This will include:
- // 1. Generating *SerializationRecord classes for each protobuf-attributed type
- // 2. Generating ToProtobuf()/FromProtobuf() extension methods
- // 3. Generating JsSyncManager registration code for ProtoContractTypes dictionary
- // 4. Copying .proto definitions to TypeScript for JS-side deserialization
+ context.CancellationToken.ThrowIfCancellationRequested();
+
+ SerializationGenerator.GenerateSerializationDataClass(context,
+ pipeline.Types, protoDefinitions, false, showDialog, sessionId);
+
+ context.CancellationToken.ThrowIfCancellationRequested();
+
+ if (showDialog)
+ {
+ ProcessHelper.CloseDialog(sessionId);
+ }
+ }
+ catch (Exception ex)
+ {
+ ProcessHelper.Log(nameof(ProtobufSourceGenerator),
+ $"Error generating serialization data class: {ex.Message}\n{ex.StackTrace}",
+ DiagnosticSeverity.Error,
+ context, showDialog, sessionId);
+
+ if (showDialog)
+ {
+ ProcessHelper.CloseDialog(sessionId);
+ }
+ }
}
}
+ private static string? _corePath;
private const string ProtoContractAttribute = "ProtoContract";
private const string ProtoSerializableAttribute = "ProtobufSerializable";
private const string SerializedMethodAttributeName = "SerializedMethod";
diff --git a/src/dymaptic.GeoBlazor.Core.sln b/src/dymaptic.GeoBlazor.Core.sln
index f476ec49f..fa5d43162 100644
--- a/src/dymaptic.GeoBlazor.Core.sln
+++ b/src/dymaptic.GeoBlazor.Core.sln
@@ -42,6 +42,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dymaptic.GeoBlazor.Core.Sam
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dymaptic.GeoBlazor.Core.Analyzers", "dymaptic.GeoBlazor.Core.Analyzers\dymaptic.GeoBlazor.Core.Analyzers.csproj", "{468F9CE4-A24F-4EE0-9C5B-2AF88A369C30}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dymaptic.GeoBlazor.Core.SourceGenerator.Shared", "dymaptic.GeoBlazor.Core.SourceGenerator.Shared\dymaptic.GeoBlazor.Core.SourceGenerator.Shared.csproj", "{8FDFC824-2365-4467-9326-DFDFF6D6B775}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dymaptic.GeoBlazor.Core.Test.Automation", "..\test\dymaptic.GeoBlazor.Core.Test.Automation\dymaptic.GeoBlazor.Core.Test.Automation.csproj", "{679E2D83-C4D8-4350-83DC-9780364A0815}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dymaptic.GeoBlazor.Core.Test.Automation.SourceGeneration", "..\test\dymaptic.GeoBlazor.Core.Test.Automation.SourceGeneration\dymaptic.GeoBlazor.Core.Test.Automation.SourceGeneration.csproj", "{B70AE99D-782B-48E7-8713-DFAEB57809FF}"
@@ -286,6 +288,18 @@ Global
{B70AE99D-782B-48E7-8713-DFAEB57809FF}.Release|x64.Build.0 = Release|Any CPU
{B70AE99D-782B-48E7-8713-DFAEB57809FF}.Release|x86.ActiveCfg = Release|Any CPU
{B70AE99D-782B-48E7-8713-DFAEB57809FF}.Release|x86.Build.0 = Release|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Debug|x64.Build.0 = Debug|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Debug|x86.Build.0 = Debug|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Release|x64.ActiveCfg = Release|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Release|x64.Build.0 = Release|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Release|x86.ActiveCfg = Release|Any CPU
+ {8FDFC824-2365-4467-9326-DFDFF6D6B775}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/dymaptic.GeoBlazor.Core/Components/ActionBase.cs b/src/dymaptic.GeoBlazor.Core/Components/ActionBase.cs
index 01b7613e5..8bdff5798 100644
--- a/src/dymaptic.GeoBlazor.Core/Components/ActionBase.cs
+++ b/src/dymaptic.GeoBlazor.Core/Components/ActionBase.cs
@@ -2,7 +2,8 @@ namespace dymaptic.GeoBlazor.Core.Components;
[JsonConverter(typeof(ActionBaseConverter))]
[CodeGenerationIgnore]
-public abstract partial class ActionBase : MapComponent
+[ProtobufSerializable]
+public abstract partial class ActionBase : MapComponent, IProtobufSerializable
{
///
/// The title of the action.
@@ -65,92 +66,8 @@ public async Task OnJsTriggerAction(PopupTriggerActionEvent triggerActionEvent)
///
public abstract string Type { get; }
- internal abstract ActionBaseSerializationRecord ToSerializationRecord();
-}
-
-[ProtoContract(Name = "Action")]
-internal record ActionBaseSerializationRecord : MapComponentSerializationRecord
-{
- public ActionBaseSerializationRecord()
- {
- }
-
- public ActionBaseSerializationRecord(string Id,
- string Type,
- string? Title,
- string? ClassName,
- bool? Active,
- bool? Disabled,
- bool? Visible,
- string? ActionId)
- {
- this.Id = Id;
- this.Type = Type;
- this.Title = Title;
- this.ClassName = ClassName;
- this.Active = Active;
- this.Disabled = Disabled;
- this.Visible = Visible;
- this.ActionId = ActionId;
- }
-
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [ProtoMember(1)]
- public string Type { get; init; } = string.Empty;
-
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [ProtoMember(2)]
- public string? Title { get; init; }
-
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [ProtoMember(3)]
- public string? ClassName { get; init; }
-
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [ProtoMember(4)]
- public bool? Active { get; init; }
-
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [ProtoMember(5)]
- public bool? Disabled { get; init; }
-
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [ProtoMember(6)]
- public bool? Visible { get; init; }
-
- [ProtoMember(7)]
- public string? Id { get; init; }
-
- [ProtoMember(8)]
- public string? Image { get; init; }
-
- [ProtoMember(9)]
- public bool? Value { get; init; }
-
- [ProtoMember(10)]
- public string? ActionId { get; init; }
-
- public ActionBase FromSerializationRecord()
- {
- Guid id = Guid.NewGuid();
- if (Guid.TryParse(Id, out Guid guidId))
- {
- id = guidId;
- }
-
- return Type switch
- {
- "button" => new ActionButton(Title, Image, ActionId, null, ClassName, Active, Disabled, Visible)
- {
- Id = id
- },
- "toggle" => new ActionToggle(Title, ActionId, null, Value, Active, Disabled, Visible)
- {
- Id = id
- },
- _ => throw new NotSupportedException()
- };
- }
+ ///
+ public abstract ActionBaseSerializationRecord ToProtobuf();
}
internal class ActionBaseConverter : JsonConverter
diff --git a/src/dymaptic.GeoBlazor.Core/Components/ActionButton.cs b/src/dymaptic.GeoBlazor.Core/Components/ActionButton.cs
index 3e67715c3..ac748e136 100644
--- a/src/dymaptic.GeoBlazor.Core/Components/ActionButton.cs
+++ b/src/dymaptic.GeoBlazor.Core/Components/ActionButton.cs
@@ -1,10 +1,9 @@
namespace dymaptic.GeoBlazor.Core.Components;
[CodeGenerationIgnore]
+[ProtobufSerializable]
public partial class ActionButton : ActionBase
{
-
-
///
public override string Type => "button";
@@ -15,7 +14,8 @@ public partial class ActionButton : ActionBase
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Image { get; set; }
- internal override ActionBaseSerializationRecord ToSerializationRecord()
+ ///
+ public override ActionBaseSerializationRecord ToProtobuf()
{
return new ActionBaseSerializationRecord(Id.ToString(), Type, Title, ClassName, Active, Disabled, Visible, ActionId)
{
diff --git a/src/dymaptic.GeoBlazor.Core/Components/ActionToggle.cs b/src/dymaptic.GeoBlazor.Core/Components/ActionToggle.cs
index 1d3314604..a3b94f848 100644
--- a/src/dymaptic.GeoBlazor.Core/Components/ActionToggle.cs
+++ b/src/dymaptic.GeoBlazor.Core/Components/ActionToggle.cs
@@ -1,10 +1,9 @@
namespace dymaptic.GeoBlazor.Core.Components;
[CodeGenerationIgnore]
+[ProtobufSerializable]
public partial class ActionToggle : ActionBase
{
-
-
///
public override string Type => "toggle";
@@ -15,7 +14,8 @@ public partial class ActionToggle : ActionBase
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? Value { get; set; }
- internal override ActionBaseSerializationRecord ToSerializationRecord()
+ ///
+ public override ActionBaseSerializationRecord ToProtobuf()
{
return new ActionBaseSerializationRecord(Id.ToString(), Type, Title, null, Active, Disabled, Visible, ActionId)
{
diff --git a/src/dymaptic.GeoBlazor.Core/Components/ActiveLayerInfo.gb.cs b/src/dymaptic.GeoBlazor.Core/Components/ActiveLayerInfo.gb.cs
index b6e2ab9f5..02ed73e37 100644
--- a/src/dymaptic.GeoBlazor.Core/Components/ActiveLayerInfo.gb.cs
+++ b/src/dymaptic.GeoBlazor.Core/Components/ActiveLayerInfo.gb.cs
@@ -2,7 +2,6 @@
namespace dymaptic.GeoBlazor.Core.Components;
-
///
/// GeoBlazor Docs
/// ActiveLayerInfo is added to or removed from the collection of
@@ -12,7 +11,6 @@ namespace dymaptic.GeoBlazor.Core.Components;
///
public partial class ActiveLayerInfo : MapComponent
{
-
///
/// Parameterless constructor for use as a Razor Component.
///
@@ -56,8 +54,7 @@ public ActiveLayerInfo()
/// The text string that represents the legend's title.
/// ArcGIS Maps SDK for JavaScript
///
- public ActiveLayerInfo(
- bool? hideLayersNotInCurrentView = null,
+ public ActiveLayerInfo(bool? hideLayersNotInCurrentView = null,
Layer? layer = null,
LayerView? layerView = null,
IReadOnlyList? legendElements = null,
@@ -74,10 +71,97 @@ public ActiveLayerInfo(
RespectLayerVisibility = respectLayerVisibility;
SublayerIds = sublayerIds;
Title = title;
-#pragma warning restore BL0005
+#pragma warning restore BL0005
+ }
+
+ ///
+ public override void ValidateRequiredGeneratedChildren()
+ {
+ if (Children is not null)
+ {
+ foreach (ActiveLayerInfo child in Children)
+ {
+ child.ValidateRequiredGeneratedChildren();
+ }
+ }
+
+ LayerView?.ValidateRequiredGeneratedChildren();
+
+ if (LegendElements is not null)
+ {
+ foreach (ILegendElement child in LegendElements)
+ {
+ child.ValidateRequiredGeneratedChildren();
+ }
+ }
+
+ base.ValidateRequiredGeneratedChildren();
+ }
+
+ ///
+ protected override async ValueTask RegisterGeneratedChildComponent(MapComponent child)
+ {
+ switch (child)
+ {
+ case ActiveLayerInfo children:
+ Children ??= [];
+
+ if (!Children.Contains(children))
+ {
+ Children = [..Children, children];
+ ModifiedParameters[nameof(Children)] = Children;
+ }
+
+ return true;
+ case LayerView layerView:
+ if (layerView != LayerView)
+ {
+ LayerView = layerView;
+ ModifiedParameters[nameof(LayerView)] = LayerView;
+ }
+
+ return true;
+ case ILegendElement legendElements:
+ LegendElements ??= [];
+
+ if (!LegendElements.Contains(legendElements))
+ {
+ LegendElements = [..LegendElements, legendElements];
+ ModifiedParameters[nameof(LegendElements)] = LegendElements;
+ }
+
+ return true;
+ default:
+ return await base.RegisterGeneratedChildComponent(child);
+ }
}
-
-
+
+ ///
+ protected override async ValueTask UnregisterGeneratedChildComponent(MapComponent child)
+ {
+ switch (child)
+ {
+ case ActiveLayerInfo children:
+ Children = Children?.Where(c => c != children).ToList();
+ ModifiedParameters[nameof(Children)] = Children;
+
+ return true;
+ case LayerView _:
+ LayerView = null;
+ ModifiedParameters[nameof(LayerView)] = LayerView;
+
+ return true;
+ case ILegendElement legendElements:
+ LegendElements = LegendElements?.Where(l => l != legendElements).ToList();
+ ModifiedParameters[nameof(LegendElements)] = LegendElements;
+
+ return true;
+ default:
+ return await base.UnregisterGeneratedChildComponent(child);
+ }
+ }
+
+
#region Public Properties / Blazor Parameters
///
@@ -89,7 +173,7 @@ public ActiveLayerInfo(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IReadOnlyList? Children { get; set; }
-
+
///
/// GeoBlazor Docs
/// When `true`, layers will only be shown in the legend if
@@ -101,7 +185,7 @@ public ActiveLayerInfo(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? HideLayersNotInCurrentView { get; set; }
-
+
///
/// GeoBlazor Docs
/// Indicates if the legend's display of the layer's renderer is driven by the scale of the view.
@@ -111,7 +195,7 @@ public ActiveLayerInfo(
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonInclude]
public bool? IsScaleDriven { get; protected set; }
-
+
///
/// GeoBlazor Docs
/// The layerView represented by the ActiveLayerInfo object's layer.
@@ -121,7 +205,7 @@ public ActiveLayerInfo(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public LayerView? LayerView { get; set; }
-
+
///
/// GeoBlazor Docs
/// The legendElements is constructed using the layer Renderer .
@@ -131,7 +215,7 @@ public ActiveLayerInfo(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IReadOnlyList? LegendElements { get; set; }
-
+
///
/// GeoBlazor Docs
/// The opacity of the layer or parent element.
@@ -141,7 +225,7 @@ public ActiveLayerInfo(
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonInclude]
public double? Opacity { get; protected set; }
-
+
///
/// GeoBlazor Docs
/// Indicates if the activeLayerInfo is ready.
@@ -151,7 +235,7 @@ public ActiveLayerInfo(
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonInclude]
public bool? Ready { get; protected set; }
-
+
///
/// GeoBlazor Docs
/// Determines whether to respect the properties of the layers in the map that
@@ -163,7 +247,7 @@ public ActiveLayerInfo(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? RespectLayerVisibility { get; set; }
-
+
///
/// GeoBlazor Docs
/// The scale of the view instance in which the Legend is rendered.
@@ -173,7 +257,7 @@ public ActiveLayerInfo(
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonInclude]
public double? Scale { get; protected set; }
-
+
///
/// GeoBlazor Docs
/// Only applies if the layer is a MapImageLayer .
@@ -183,7 +267,7 @@ public ActiveLayerInfo(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IReadOnlyList? SublayerIds { get; set; }
-
+
///
/// GeoBlazor Docs
/// The text string that represents the legend's title.
@@ -193,7 +277,7 @@ public ActiveLayerInfo(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Title { get; set; }
-
+
///
/// GeoBlazor Docs
/// The version of the ActiveLayerInfo.
@@ -203,9 +287,10 @@ public ActiveLayerInfo(
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonInclude]
public double? Version { get; protected set; }
-
+
#endregion
+
#region Property Getters
///
@@ -217,8 +302,8 @@ public ActiveLayerInfo(
{
return HideLayersNotInCurrentView;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -227,26 +312,28 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return HideLayersNotInCurrentView;
}
// get the property value
- JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync("getNullableValueTypedProperty",
+ JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync(
+ "getNullableValueTypedProperty",
CancellationTokenSource.Token, JsComponentReference, "hideLayersNotInCurrentView");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- HideLayersNotInCurrentView = result.Value.Value;
+ HideLayersNotInCurrentView = result.Value.Value;
#pragma warning restore BL0005
- ModifiedParameters[nameof(HideLayersNotInCurrentView)] = HideLayersNotInCurrentView;
+ ModifiedParameters[nameof(HideLayersNotInCurrentView)] = HideLayersNotInCurrentView;
}
-
+
return HideLayersNotInCurrentView;
}
-
+
///
/// Asynchronously retrieve the current value of the IsScaleDriven property.
///
@@ -256,8 +343,8 @@ public ActiveLayerInfo(
{
return IsScaleDriven;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -266,26 +353,28 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return IsScaleDriven;
}
// get the property value
- JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync("getNullableValueTypedProperty",
+ JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync(
+ "getNullableValueTypedProperty",
CancellationTokenSource.Token, JsComponentReference, "isScaleDriven");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- IsScaleDriven = result.Value.Value;
+ IsScaleDriven = result.Value.Value;
#pragma warning restore BL0005
- ModifiedParameters[nameof(IsScaleDriven)] = IsScaleDriven;
+ ModifiedParameters[nameof(IsScaleDriven)] = IsScaleDriven;
}
-
+
return IsScaleDriven;
}
-
+
///
/// Asynchronously retrieve the current value of the Layer property.
///
@@ -295,8 +384,8 @@ public ActiveLayerInfo(
{
return Layer;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -305,32 +394,32 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Layer;
}
- Layer? result = await JsComponentReference.InvokeAsync(
- "getLayer", CancellationTokenSource.Token);
-
+ Layer? result = await JsComponentReference.InvokeAsync("getLayer", CancellationTokenSource.Token);
+
if (result is not null)
{
if (Layer is not null)
{
result.Id = Layer.Id;
}
+
result.UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer);
-
+
#pragma warning disable BL0005
Layer = result;
#pragma warning restore BL0005
ModifiedParameters[nameof(Layer)] = Layer;
}
-
+
return Layer;
}
-
+
///
/// Asynchronously retrieve the current value of the LayerView property.
///
@@ -340,8 +429,8 @@ public ActiveLayerInfo(
{
return LayerView;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -350,7 +439,7 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return LayerView;
@@ -358,24 +447,25 @@ public ActiveLayerInfo(
LayerView? result = await JsComponentReference.InvokeAsync(
"getLayerView", CancellationTokenSource.Token);
-
+
if (result is not null)
{
if (LayerView is not null)
{
result.Id = LayerView.Id;
}
+
result.UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer);
-
+
#pragma warning disable BL0005
LayerView = result;
#pragma warning restore BL0005
ModifiedParameters[nameof(LayerView)] = LayerView;
}
-
+
return LayerView;
}
-
+
///
/// Asynchronously retrieve the current value of the LegendElements property.
///
@@ -385,8 +475,8 @@ public ActiveLayerInfo(
{
return LegendElements;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -395,15 +485,16 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return LegendElements;
}
- IReadOnlyList? result = await JsComponentReference.InvokeAsync?>(
- "getLegendElements", CancellationTokenSource.Token);
-
+ IReadOnlyList? result =
+ await JsComponentReference.InvokeAsync?>("getLegendElements",
+ CancellationTokenSource.Token);
+
if (result is not null)
{
foreach (ILegendElement item in result)
@@ -415,10 +506,10 @@ public ActiveLayerInfo(
#pragma warning restore BL0005
ModifiedParameters[nameof(LegendElements)] = LegendElements;
}
-
+
return LegendElements;
}
-
+
///
/// Asynchronously retrieve the current value of the Opacity property.
///
@@ -428,8 +519,8 @@ public ActiveLayerInfo(
{
return Opacity;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -438,26 +529,28 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Opacity;
}
// get the property value
- JsNullableDoubleWrapper? result = await CoreJsModule!.InvokeAsync("getNullableValueTypedProperty",
+ JsNullableDoubleWrapper? result = await CoreJsModule!.InvokeAsync(
+ "getNullableValueTypedProperty",
CancellationTokenSource.Token, JsComponentReference, "opacity");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- Opacity = result.Value.Value;
+ Opacity = result.Value.Value;
#pragma warning restore BL0005
- ModifiedParameters[nameof(Opacity)] = Opacity;
+ ModifiedParameters[nameof(Opacity)] = Opacity;
}
-
+
return Opacity;
}
-
+
///
/// Asynchronously retrieve the current value of the Ready property.
///
@@ -467,8 +560,8 @@ public ActiveLayerInfo(
{
return Ready;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -477,26 +570,28 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Ready;
}
// get the property value
- JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync("getNullableValueTypedProperty",
+ JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync(
+ "getNullableValueTypedProperty",
CancellationTokenSource.Token, JsComponentReference, "ready");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- Ready = result.Value.Value;
+ Ready = result.Value.Value;
#pragma warning restore BL0005
- ModifiedParameters[nameof(Ready)] = Ready;
+ ModifiedParameters[nameof(Ready)] = Ready;
}
-
+
return Ready;
}
-
+
///
/// Asynchronously retrieve the current value of the RespectLayerVisibility property.
///
@@ -506,8 +601,8 @@ public ActiveLayerInfo(
{
return RespectLayerVisibility;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -516,26 +611,28 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return RespectLayerVisibility;
}
// get the property value
- JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync("getNullableValueTypedProperty",
+ JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync(
+ "getNullableValueTypedProperty",
CancellationTokenSource.Token, JsComponentReference, "respectLayerVisibility");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- RespectLayerVisibility = result.Value.Value;
+ RespectLayerVisibility = result.Value.Value;
#pragma warning restore BL0005
- ModifiedParameters[nameof(RespectLayerVisibility)] = RespectLayerVisibility;
+ ModifiedParameters[nameof(RespectLayerVisibility)] = RespectLayerVisibility;
}
-
+
return RespectLayerVisibility;
}
-
+
///
/// Asynchronously retrieve the current value of the Scale property.
///
@@ -545,8 +642,8 @@ public ActiveLayerInfo(
{
return Scale;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -555,26 +652,28 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Scale;
}
// get the property value
- JsNullableDoubleWrapper? result = await CoreJsModule!.InvokeAsync("getNullableValueTypedProperty",
+ JsNullableDoubleWrapper? result = await CoreJsModule!.InvokeAsync(
+ "getNullableValueTypedProperty",
CancellationTokenSource.Token, JsComponentReference, "scale");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- Scale = result.Value.Value;
+ Scale = result.Value.Value;
#pragma warning restore BL0005
- ModifiedParameters[nameof(Scale)] = Scale;
+ ModifiedParameters[nameof(Scale)] = Scale;
}
-
+
return Scale;
}
-
+
///
/// Asynchronously retrieve the current value of the SublayerIds property.
///
@@ -584,8 +683,8 @@ public ActiveLayerInfo(
{
return SublayerIds;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -594,7 +693,7 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return SublayerIds;
@@ -603,17 +702,18 @@ public ActiveLayerInfo(
// get the property value
IReadOnlyList? result = await JsComponentReference!.InvokeAsync?>("getProperty",
CancellationTokenSource.Token, "sublayerIds");
+
if (result is not null)
{
#pragma warning disable BL0005
- SublayerIds = result;
+ SublayerIds = result;
#pragma warning restore BL0005
- ModifiedParameters[nameof(SublayerIds)] = SublayerIds;
+ ModifiedParameters[nameof(SublayerIds)] = SublayerIds;
}
-
+
return SublayerIds;
}
-
+
///
/// Asynchronously retrieve the current value of the Title property.
///
@@ -623,8 +723,8 @@ public ActiveLayerInfo(
{
return Title;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -633,7 +733,7 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Title;
@@ -642,17 +742,18 @@ public ActiveLayerInfo(
// get the property value
string? result = await JsComponentReference!.InvokeAsync("getProperty",
CancellationTokenSource.Token, "title");
+
if (result is not null)
{
#pragma warning disable BL0005
- Title = result;
+ Title = result;
#pragma warning restore BL0005
- ModifiedParameters[nameof(Title)] = Title;
+ ModifiedParameters[nameof(Title)] = Title;
}
-
+
return Title;
}
-
+
///
/// Asynchronously retrieve the current value of the Version property.
///
@@ -662,8 +763,8 @@ public ActiveLayerInfo(
{
return Version;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -672,28 +773,31 @@ public ActiveLayerInfo(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Version;
}
// get the property value
- JsNullableDoubleWrapper? result = await CoreJsModule!.InvokeAsync("getNullableValueTypedProperty",
+ JsNullableDoubleWrapper? result = await CoreJsModule!.InvokeAsync(
+ "getNullableValueTypedProperty",
CancellationTokenSource.Token, JsComponentReference, "version");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- Version = result.Value.Value;
+ Version = result.Value.Value;
#pragma warning restore BL0005
- ModifiedParameters[nameof(Version)] = Version;
+ ModifiedParameters[nameof(Version)] = Version;
}
-
+
return Version;
}
-
+
#endregion
+
#region Property Setters
///
@@ -708,13 +812,13 @@ public async Task SetHideLayersNotInCurrentView(bool? value)
HideLayersNotInCurrentView = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(HideLayersNotInCurrentView)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -723,16 +827,16 @@ public async Task SetHideLayersNotInCurrentView(bool? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "hideLayersNotInCurrentView", value);
}
-
+
///
/// Asynchronously set the value of the Layer property after render.
///
@@ -744,19 +848,19 @@ public async Task SetLayer(Layer? value)
if (value is not null)
{
value.UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer);
- }
-
+ }
+
#pragma warning disable BL0005
Layer = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(Layer)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -765,16 +869,16 @@ public async Task SetLayer(Layer? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "layer", value);
}
-
+
///
/// Asynchronously set the value of the LayerView property after render.
///
@@ -786,19 +890,19 @@ public async Task SetLayerView(LayerView? value)
if (value is not null)
{
value.UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer);
- }
-
+ }
+
#pragma warning disable BL0005
LayerView = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(LayerView)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -807,16 +911,16 @@ public async Task SetLayerView(LayerView? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "layerView", value);
}
-
+
///
/// Asynchronously set the value of the LegendElements property after render.
///
@@ -832,18 +936,18 @@ public async Task SetLegendElements(IReadOnlyList? value)
((MapComponent)item).UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer);
}
}
-
+
#pragma warning disable BL0005
LegendElements = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(LegendElements)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -852,16 +956,16 @@ public async Task SetLegendElements(IReadOnlyList? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "legendElements", value);
}
-
+
///
/// Asynchronously set the value of the RespectLayerVisibility property after render.
///
@@ -874,13 +978,13 @@ public async Task SetRespectLayerVisibility(bool? value)
RespectLayerVisibility = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(RespectLayerVisibility)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -889,16 +993,16 @@ public async Task SetRespectLayerVisibility(bool? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "respectLayerVisibility", value);
}
-
+
///
/// Asynchronously set the value of the SublayerIds property after render.
///
@@ -911,13 +1015,13 @@ public async Task SetSublayerIds(IReadOnlyList? value)
SublayerIds = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(SublayerIds)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -926,16 +1030,16 @@ public async Task SetSublayerIds(IReadOnlyList? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "sublayerIds", value);
}
-
+
///
/// Asynchronously set the value of the Title property after render.
///
@@ -948,13 +1052,13 @@ public async Task SetTitle(string? value)
Title = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(Title)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -963,18 +1067,19 @@ public async Task SetTitle(string? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "title", value);
}
-
+
#endregion
+
#region Add to Collection Methods
///
@@ -990,7 +1095,7 @@ public async Task AddToLegendElements(params ILegendElement[] values)
: [..LegendElements, ..values];
await SetLegendElements(join);
}
-
+
///
/// Asynchronously adds elements to the SublayerIds property.
///
@@ -1004,12 +1109,12 @@ public async Task AddToSublayerIds(params long[] values)
: [..SublayerIds, ..values];
await SetSublayerIds(join);
}
-
+
#endregion
+
#region Remove From Collection Methods
-
///
/// Asynchronously remove an element from the LegendElements property.
///
@@ -1022,10 +1127,10 @@ public async Task RemoveFromLegendElements(params ILegendElement[] values)
{
return;
}
+
await SetLegendElements(LegendElements.Except(values).ToArray());
}
-
-
+
///
/// Asynchronously remove an element from the SublayerIds property.
///
@@ -1038,90 +1143,9 @@ public async Task RemoveFromSublayerIds(params long[] values)
{
return;
}
- await SetSublayerIds(SublayerIds.Except(values).ToArray());
- }
-
-#endregion
-
- ///
- protected override async ValueTask RegisterGeneratedChildComponent(MapComponent child)
- {
- switch (child)
- {
- case ActiveLayerInfo children:
- Children ??= [];
- if (!Children.Contains(children))
- {
- Children = [..Children, children];
- ModifiedParameters[nameof(Children)] = Children;
- }
-
- return true;
- case LayerView layerView:
- if (layerView != LayerView)
- {
- LayerView = layerView;
- ModifiedParameters[nameof(LayerView)] = LayerView;
- }
-
- return true;
- case ILegendElement legendElements:
- LegendElements ??= [];
- if (!LegendElements.Contains(legendElements))
- {
- LegendElements = [..LegendElements, legendElements];
- ModifiedParameters[nameof(LegendElements)] = LegendElements;
- }
-
- return true;
- default:
- return await base.RegisterGeneratedChildComponent(child);
- }
+ await SetSublayerIds(SublayerIds.Except(values).ToArray());
}
- ///
- protected override async ValueTask UnregisterGeneratedChildComponent(MapComponent child)
- {
- switch (child)
- {
- case ActiveLayerInfo children:
- Children = Children?.Where(c => c != children).ToList();
- ModifiedParameters[nameof(Children)] = Children;
- return true;
- case LayerView _:
- LayerView = null;
- ModifiedParameters[nameof(LayerView)] = LayerView;
- return true;
- case ILegendElement legendElements:
- LegendElements = LegendElements?.Where(l => l != legendElements).ToList();
- ModifiedParameters[nameof(LegendElements)] = LegendElements;
- return true;
- default:
- return await base.UnregisterGeneratedChildComponent(child);
- }
- }
-
- ///
- public override void ValidateRequiredGeneratedChildren()
- {
-
- if (Children is not null)
- {
- foreach (ActiveLayerInfo child in Children)
- {
- child.ValidateRequiredGeneratedChildren();
- }
- }
- LayerView?.ValidateRequiredGeneratedChildren();
- if (LegendElements is not null)
- {
- foreach (ILegendElement child in LegendElements)
- {
- child.ValidateRequiredGeneratedChildren();
- }
- }
- base.ValidateRequiredGeneratedChildren();
- }
-
-}
+#endregion
+}
\ No newline at end of file
diff --git a/src/dymaptic.GeoBlazor.Core/Components/AggregateField.gb.cs b/src/dymaptic.GeoBlazor.Core/Components/AggregateField.gb.cs
index 84604db58..f1d56f71c 100644
--- a/src/dymaptic.GeoBlazor.Core/Components/AggregateField.gb.cs
+++ b/src/dymaptic.GeoBlazor.Core/Components/AggregateField.gb.cs
@@ -2,7 +2,6 @@
namespace dymaptic.GeoBlazor.Core.Components;
-
///
/// GeoBlazor Docs
/// Defines the aggregate fields used in a layer visualized with
@@ -12,7 +11,6 @@ namespace dymaptic.GeoBlazor.Core.Components;
///
public partial class AggregateField
{
-
///
/// Parameterless constructor for use as a Razor Component.
///
@@ -54,8 +52,7 @@ public AggregateField()
/// or onStatisticExpression .
/// ArcGIS Maps SDK for JavaScript
///
- public AggregateField(
- string? alias = null,
+ public AggregateField(string? alias = null,
bool? isAutoGenerated = null,
string? name = null,
SupportExpressionInfo? onStatisticExpression = null,
@@ -70,10 +67,10 @@ public AggregateField(
OnStatisticExpression = onStatisticExpression;
OnStatisticField = onStatisticField;
StatisticType = statisticType;
-#pragma warning restore BL0005
+#pragma warning restore BL0005
}
-
-
+
+
#region Public Properties / Blazor Parameters
///
@@ -86,9 +83,51 @@ public AggregateField(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SupportExpressionInfo? OnStatisticExpression { get; set; }
-
+
#endregion
+
+ ///
+ public override void ValidateRequiredGeneratedChildren()
+ {
+ OnStatisticExpression?.ValidateRequiredGeneratedChildren();
+ base.ValidateRequiredGeneratedChildren();
+ }
+
+ ///
+ protected override async ValueTask RegisterGeneratedChildComponent(MapComponent child)
+ {
+ switch (child)
+ {
+ case SupportExpressionInfo onStatisticExpression:
+ if (onStatisticExpression != OnStatisticExpression)
+ {
+ OnStatisticExpression = onStatisticExpression;
+ ModifiedParameters[nameof(OnStatisticExpression)] = OnStatisticExpression;
+ }
+
+ return true;
+ default:
+ return await base.RegisterGeneratedChildComponent(child);
+ }
+ }
+
+ ///
+ protected override async ValueTask UnregisterGeneratedChildComponent(MapComponent child)
+ {
+ switch (child)
+ {
+ case SupportExpressionInfo _:
+ OnStatisticExpression = null;
+ ModifiedParameters[nameof(OnStatisticExpression)] = OnStatisticExpression;
+
+ return true;
+ default:
+ return await base.UnregisterGeneratedChildComponent(child);
+ }
+ }
+
+
#region Property Getters
///
@@ -100,8 +139,8 @@ public AggregateField(
{
return Alias;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -110,7 +149,7 @@ public AggregateField(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Alias;
@@ -119,17 +158,18 @@ public AggregateField(
// get the property value
string? result = await JsComponentReference!.InvokeAsync("getProperty",
CancellationTokenSource.Token, "alias");
+
if (result is not null)
{
#pragma warning disable BL0005
- Alias = result;
+ Alias = result;
#pragma warning restore BL0005
- ModifiedParameters[nameof(Alias)] = Alias;
+ ModifiedParameters[nameof(Alias)] = Alias;
}
-
+
return Alias;
}
-
+
///
/// Asynchronously retrieve the current value of the IsAutoGenerated property.
///
@@ -139,8 +179,8 @@ public AggregateField(
{
return IsAutoGenerated;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -149,26 +189,28 @@ public AggregateField(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return IsAutoGenerated;
}
// get the property value
- JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync("getNullableValueTypedProperty",
+ JsNullableBoolWrapper? result = await CoreJsModule!.InvokeAsync(
+ "getNullableValueTypedProperty",
CancellationTokenSource.Token, JsComponentReference, "isAutoGenerated");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- IsAutoGenerated = result.Value.Value;
+ IsAutoGenerated = result.Value.Value;
#pragma warning restore BL0005
- ModifiedParameters[nameof(IsAutoGenerated)] = IsAutoGenerated;
+ ModifiedParameters[nameof(IsAutoGenerated)] = IsAutoGenerated;
}
-
+
return IsAutoGenerated;
}
-
+
///
/// Asynchronously retrieve the current value of the Name property.
///
@@ -178,8 +220,8 @@ public AggregateField(
{
return Name;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -188,7 +230,7 @@ public AggregateField(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Name;
@@ -197,17 +239,18 @@ public AggregateField(
// get the property value
string? result = await JsComponentReference!.InvokeAsync("getProperty",
CancellationTokenSource.Token, "name");
+
if (result is not null)
{
#pragma warning disable BL0005
- Name = result;
+ Name = result;
#pragma warning restore BL0005
- ModifiedParameters[nameof(Name)] = Name;
+ ModifiedParameters[nameof(Name)] = Name;
}
-
+
return Name;
}
-
+
///
/// Asynchronously retrieve the current value of the OnStatisticExpression property.
///
@@ -217,8 +260,8 @@ public AggregateField(
{
return OnStatisticExpression;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -227,7 +270,7 @@ public AggregateField(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return OnStatisticExpression;
@@ -235,7 +278,7 @@ public AggregateField(
SupportExpressionInfo? result = await JsComponentReference.InvokeAsync(
"getOnStatisticExpression", CancellationTokenSource.Token);
-
+
if (result is not null)
{
#pragma warning disable BL0005
@@ -243,10 +286,10 @@ public AggregateField(
#pragma warning restore BL0005
ModifiedParameters[nameof(OnStatisticExpression)] = OnStatisticExpression;
}
-
+
return OnStatisticExpression;
}
-
+
///
/// Asynchronously retrieve the current value of the OnStatisticField property.
///
@@ -256,8 +299,8 @@ public AggregateField(
{
return OnStatisticField;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -266,7 +309,7 @@ public AggregateField(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return OnStatisticField;
@@ -275,17 +318,18 @@ public AggregateField(
// get the property value
string? result = await JsComponentReference!.InvokeAsync("getProperty",
CancellationTokenSource.Token, "onStatisticField");
+
if (result is not null)
{
#pragma warning disable BL0005
- OnStatisticField = result;
+ OnStatisticField = result;
#pragma warning restore BL0005
- ModifiedParameters[nameof(OnStatisticField)] = OnStatisticField;
+ ModifiedParameters[nameof(OnStatisticField)] = OnStatisticField;
}
-
+
return OnStatisticField;
}
-
+
///
/// Asynchronously retrieve the current value of the StatisticType property.
///
@@ -295,8 +339,8 @@ public AggregateField(
{
return StatisticType;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -305,28 +349,32 @@ public AggregateField(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return StatisticType;
}
// get the property value
- JsNullableEnumWrapper? result = await CoreJsModule!.InvokeAsync?>("getNullableValueTypedProperty",
- CancellationTokenSource.Token, JsComponentReference, "statisticType");
+ JsNullableEnumWrapper? result =
+ await CoreJsModule!.InvokeAsync?>(
+ "getNullableValueTypedProperty",
+ CancellationTokenSource.Token, JsComponentReference, "statisticType");
+
if (result is { Value: not null })
{
#pragma warning disable BL0005
- StatisticType = (AggregateStatisticType)result.Value.Value!;
+ StatisticType = (AggregateStatisticType)result.Value.Value!;
#pragma warning restore BL0005
- ModifiedParameters[nameof(StatisticType)] = StatisticType;
+ ModifiedParameters[nameof(StatisticType)] = StatisticType;
}
-
+
return StatisticType;
}
-
+
#endregion
+
#region Property Setters
///
@@ -341,13 +389,13 @@ public async Task SetAlias(string? value)
Alias = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(Alias)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -356,16 +404,16 @@ public async Task SetAlias(string? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "alias", value);
}
-
+
///
/// Asynchronously set the value of the IsAutoGenerated property after render.
///
@@ -378,13 +426,13 @@ public async Task SetIsAutoGenerated(bool? value)
IsAutoGenerated = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(IsAutoGenerated)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -393,16 +441,16 @@ public async Task SetIsAutoGenerated(bool? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "isAutoGenerated", value);
}
-
+
///
/// Asynchronously set the value of the Name property after render.
///
@@ -415,13 +463,13 @@ public async Task SetName(string? value)
Name = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(Name)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -430,16 +478,16 @@ public async Task SetName(string? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "name", value);
}
-
+
///
/// Asynchronously set the value of the OnStatisticExpression property after render.
///
@@ -451,19 +499,19 @@ public async Task SetOnStatisticExpression(SupportExpressionInfo? value)
if (value is not null)
{
value.UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer);
- }
-
+ }
+
#pragma warning disable BL0005
OnStatisticExpression = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(OnStatisticExpression)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -472,16 +520,16 @@ public async Task SetOnStatisticExpression(SupportExpressionInfo? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "onStatisticExpression", value);
}
-
+
///
/// Asynchronously set the value of the OnStatisticField property after render.
///
@@ -494,13 +542,13 @@ public async Task SetOnStatisticField(string? value)
OnStatisticField = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(OnStatisticField)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -509,16 +557,16 @@ public async Task SetOnStatisticField(string? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "onStatisticField", value);
}
-
+
///
/// Asynchronously set the value of the StatisticType property after render.
///
@@ -531,13 +579,13 @@ public async Task SetStatisticType(AggregateStatisticType? value)
StatisticType = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(StatisticType)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -546,57 +594,15 @@ public async Task SetStatisticType(AggregateStatisticType? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "statisticType", value);
}
-
-#endregion
-
-
- ///
- protected override async ValueTask RegisterGeneratedChildComponent(MapComponent child)
- {
- switch (child)
- {
- case SupportExpressionInfo onStatisticExpression:
- if (onStatisticExpression != OnStatisticExpression)
- {
- OnStatisticExpression = onStatisticExpression;
- ModifiedParameters[nameof(OnStatisticExpression)] = OnStatisticExpression;
- }
-
- return true;
- default:
- return await base.RegisterGeneratedChildComponent(child);
- }
- }
- ///
- protected override async ValueTask UnregisterGeneratedChildComponent(MapComponent child)
- {
- switch (child)
- {
- case SupportExpressionInfo _:
- OnStatisticExpression = null;
- ModifiedParameters[nameof(OnStatisticExpression)] = OnStatisticExpression;
- return true;
- default:
- return await base.UnregisterGeneratedChildComponent(child);
- }
- }
-
- ///
- public override void ValidateRequiredGeneratedChildren()
- {
-
- OnStatisticExpression?.ValidateRequiredGeneratedChildren();
- base.ValidateRequiredGeneratedChildren();
- }
-
-}
+#endregion
+}
\ No newline at end of file
diff --git a/src/dymaptic.GeoBlazor.Core/Components/ApplicationProperties.gb.cs b/src/dymaptic.GeoBlazor.Core/Components/ApplicationProperties.gb.cs
index eb6ba0a51..b5699fda9 100644
--- a/src/dymaptic.GeoBlazor.Core/Components/ApplicationProperties.gb.cs
+++ b/src/dymaptic.GeoBlazor.Core/Components/ApplicationProperties.gb.cs
@@ -2,7 +2,6 @@
namespace dymaptic.GeoBlazor.Core.Components;
-
///
/// GeoBlazor Docs
/// Represents configuration of application and UI elements of the
@@ -11,7 +10,6 @@ namespace dymaptic.GeoBlazor.Core.Components;
///
public partial class ApplicationProperties : MapComponent
{
-
///
/// Parameterless constructor for use as a Razor Component.
///
@@ -27,16 +25,15 @@ public ApplicationProperties()
/// View-specific properties of application and UI elements for the web map.
/// ArcGIS Maps SDK for JavaScript
///
- public ApplicationProperties(
- Viewing? viewing = null)
+ public ApplicationProperties(Viewing? viewing = null)
{
AllowRender = false;
#pragma warning disable BL0005
Viewing = viewing;
-#pragma warning restore BL0005
+#pragma warning restore BL0005
}
-
-
+
+
#region Public Properties / Blazor Parameters
///
@@ -48,9 +45,10 @@ public ApplicationProperties(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Viewing? Viewing { get; set; }
-
+
#endregion
+
#region Property Getters
///
@@ -62,8 +60,8 @@ public ApplicationProperties(
{
return Viewing;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -72,15 +70,14 @@ public ApplicationProperties(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Viewing;
}
- Viewing? result = await JsComponentReference.InvokeAsync(
- "getViewing", CancellationTokenSource.Token);
-
+ Viewing? result = await JsComponentReference.InvokeAsync("getViewing", CancellationTokenSource.Token);
+
if (result is not null)
{
#pragma warning disable BL0005
@@ -88,12 +85,13 @@ public ApplicationProperties(
#pragma warning restore BL0005
ModifiedParameters[nameof(Viewing)] = Viewing;
}
-
+
return Viewing;
}
-
+
#endregion
+
#region Property Setters
///
@@ -107,19 +105,19 @@ public async Task SetViewing(Viewing? value)
if (value is not null)
{
value.UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer);
- }
-
+ }
+
#pragma warning disable BL0005
Viewing = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(Viewing)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -128,19 +126,26 @@ public async Task SetViewing(Viewing? value)
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "viewing", value);
}
-
+
#endregion
+ ///
+ public override void ValidateRequiredGeneratedChildren()
+ {
+ Viewing?.ValidateRequiredGeneratedChildren();
+ base.ValidateRequiredGeneratedChildren();
+ }
+
///
protected override async ValueTask RegisterGeneratedChildComponent(MapComponent child)
{
@@ -152,7 +157,7 @@ protected override async ValueTask RegisterGeneratedChildComponent(MapComp
Viewing = viewing;
ModifiedParameters[nameof(Viewing)] = Viewing;
}
-
+
return true;
default:
return await base.RegisterGeneratedChildComponent(child);
@@ -167,18 +172,10 @@ protected override async ValueTask UnregisterGeneratedChildComponent(MapCo
case Viewing _:
Viewing = null;
ModifiedParameters[nameof(Viewing)] = Viewing;
+
return true;
default:
return await base.UnregisterGeneratedChildComponent(child);
}
}
-
- ///
- public override void ValidateRequiredGeneratedChildren()
- {
-
- Viewing?.ValidateRequiredGeneratedChildren();
- base.ValidateRequiredGeneratedChildren();
- }
-
-}
+}
\ No newline at end of file
diff --git a/src/dymaptic.GeoBlazor.Core/Components/ArcGISImageServiceCapabilities.gb.cs b/src/dymaptic.GeoBlazor.Core/Components/ArcGISImageServiceCapabilities.gb.cs
index 184a44f2c..224a23848 100644
--- a/src/dymaptic.GeoBlazor.Core/Components/ArcGISImageServiceCapabilities.gb.cs
+++ b/src/dymaptic.GeoBlazor.Core/Components/ArcGISImageServiceCapabilities.gb.cs
@@ -2,7 +2,6 @@
namespace dymaptic.GeoBlazor.Core.Components;
-
///
/// GeoBlazor Docs
/// Describes the layer's supported capabilities.
@@ -10,7 +9,6 @@ namespace dymaptic.GeoBlazor.Core.Components;
///
public partial class ArcGISImageServiceCapabilities : MapComponent
{
-
///
/// Parameterless constructor for use as a Razor Component.
///
@@ -34,8 +32,7 @@ public ArcGISImageServiceCapabilities()
/// Describes query operations supported by the layer.
/// ArcGIS Maps SDK for JavaScript
///
- public ArcGISImageServiceCapabilities(
- ArcGISImageServiceCapabilitiesMensuration? mensuration = null,
+ public ArcGISImageServiceCapabilities(ArcGISImageServiceCapabilitiesMensuration? mensuration = null,
ArcGISImageServiceCapabilitiesOperations? operations = null,
ArcGISImageServiceCapabilitiesQuery? query = null)
{
@@ -44,10 +41,64 @@ public ArcGISImageServiceCapabilities(
Mensuration = mensuration;
Operations = operations;
Query = query;
-#pragma warning restore BL0005
+#pragma warning restore BL0005
+ }
+
+ ///
+ public override void ValidateRequiredGeneratedChildren()
+ {
+ Mensuration?.ValidateRequiredGeneratedChildren();
+ Operations?.ValidateRequiredGeneratedChildren();
+ base.ValidateRequiredGeneratedChildren();
+ }
+
+ ///
+ protected override async ValueTask RegisterGeneratedChildComponent(MapComponent child)
+ {
+ switch (child)
+ {
+ case ArcGISImageServiceCapabilitiesMensuration mensuration:
+ if (mensuration != Mensuration)
+ {
+ Mensuration = mensuration;
+ ModifiedParameters[nameof(Mensuration)] = Mensuration;
+ }
+
+ return true;
+ case ArcGISImageServiceCapabilitiesOperations operations:
+ if (operations != Operations)
+ {
+ Operations = operations;
+ ModifiedParameters[nameof(Operations)] = Operations;
+ }
+
+ return true;
+ default:
+ return await base.RegisterGeneratedChildComponent(child);
+ }
}
-
-
+
+ ///
+ protected override async ValueTask UnregisterGeneratedChildComponent(MapComponent child)
+ {
+ switch (child)
+ {
+ case ArcGISImageServiceCapabilitiesMensuration _:
+ Mensuration = null;
+ ModifiedParameters[nameof(Mensuration)] = Mensuration;
+
+ return true;
+ case ArcGISImageServiceCapabilitiesOperations _:
+ Operations = null;
+ ModifiedParameters[nameof(Operations)] = Operations;
+
+ return true;
+ default:
+ return await base.UnregisterGeneratedChildComponent(child);
+ }
+ }
+
+
#region Public Properties / Blazor Parameters
///
@@ -59,7 +110,7 @@ public ArcGISImageServiceCapabilities(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ArcGISImageServiceCapabilitiesMensuration? Mensuration { get; set; }
-
+
///
/// GeoBlazor Docs
/// Describes operations supported by the ImageryLayer.
@@ -69,7 +120,7 @@ public ArcGISImageServiceCapabilities(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ArcGISImageServiceCapabilitiesOperations? Operations { get; set; }
-
+
///
/// GeoBlazor Docs
/// Describes query operations supported by the layer.
@@ -79,9 +130,10 @@ public ArcGISImageServiceCapabilities(
[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ArcGISImageServiceCapabilitiesQuery? Query { get; set; }
-
+
#endregion
+
#region Property Getters
///
@@ -93,8 +145,8 @@ public ArcGISImageServiceCapabilities(
{
return Mensuration;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -103,15 +155,16 @@ public ArcGISImageServiceCapabilities(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Mensuration;
}
- ArcGISImageServiceCapabilitiesMensuration? result = await JsComponentReference.InvokeAsync(
- "getMensuration", CancellationTokenSource.Token);
-
+ ArcGISImageServiceCapabilitiesMensuration? result =
+ await JsComponentReference.InvokeAsync("getMensuration",
+ CancellationTokenSource.Token);
+
if (result is not null)
{
#pragma warning disable BL0005
@@ -119,10 +172,10 @@ public ArcGISImageServiceCapabilities(
#pragma warning restore BL0005
ModifiedParameters[nameof(Mensuration)] = Mensuration;
}
-
+
return Mensuration;
}
-
+
///
/// Asynchronously retrieve the current value of the Operations property.
///
@@ -132,8 +185,8 @@ public ArcGISImageServiceCapabilities(
{
return Operations;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -142,15 +195,16 @@ public ArcGISImageServiceCapabilities(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Operations;
}
- ArcGISImageServiceCapabilitiesOperations? result = await JsComponentReference.InvokeAsync(
- "getOperations", CancellationTokenSource.Token);
-
+ ArcGISImageServiceCapabilitiesOperations? result =
+ await JsComponentReference.InvokeAsync("getOperations",
+ CancellationTokenSource.Token);
+
if (result is not null)
{
#pragma warning disable BL0005
@@ -158,10 +212,10 @@ public ArcGISImageServiceCapabilities(
#pragma warning restore BL0005
ModifiedParameters[nameof(Operations)] = Operations;
}
-
+
return Operations;
}
-
+
///
/// Asynchronously retrieve the current value of the Query property.
///
@@ -171,8 +225,8 @@ public ArcGISImageServiceCapabilities(
{
return Query;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -181,28 +235,31 @@ public ArcGISImageServiceCapabilities(
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return Query;
}
// get the property value
- ArcGISImageServiceCapabilitiesQuery? result = await JsComponentReference!.InvokeAsync("getProperty",
- CancellationTokenSource.Token, "query");
+ ArcGISImageServiceCapabilitiesQuery? result =
+ await JsComponentReference!.InvokeAsync("getProperty",
+ CancellationTokenSource.Token, "query");
+
if (result is not null)
{
#pragma warning disable BL0005
- Query = result;
+ Query = result;
#pragma warning restore BL0005
- ModifiedParameters[nameof(Query)] = Query;
+ ModifiedParameters[nameof(Query)] = Query;
}
-
+
return Query;
}
-
+
#endregion
+
#region Property Setters
///
@@ -216,19 +273,19 @@ public async Task SetMensuration(ArcGISImageServiceCapabilitiesMensuration? valu
if (value is not null)
{
value.UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer);
- }
-
+ }
+
#pragma warning disable BL0005
Mensuration = value;
#pragma warning restore BL0005
ModifiedParameters[nameof(Mensuration)] = value;
-
+
if (CoreJsModule is null)
{
return;
}
-
- try
+
+ try
{
JsComponentReference ??= await CoreJsModule.InvokeAsync(
"getJsComponent", CancellationTokenSource.Token, Id);
@@ -237,16 +294,16 @@ public async Task SetMensuration(ArcGISImageServiceCapabilitiesMensuration? valu
{
// this is expected if the component is not yet built
}
-
+
if (JsComponentReference is null)
{
return;
}
-
+
await CoreJsModule.InvokeVoidAsync("setProperty", CancellationTokenSource.Token,
JsComponentReference, "mensuration", value);
}
-
+
///