Skip to content

Commit a55d8ba

Browse files
committed
Added generated code visualisation with some error handlings
1 parent 3a2970a commit a55d8ba

File tree

15 files changed

+864
-799
lines changed

15 files changed

+864
-799
lines changed

src/NodeDev.Blazor.Server/Pages/_Layout.cshtml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
1414
<link href="_content/NodeDev.Blazor/styles.css" rel="stylesheet" />
1515

16+
<link href="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet" />
17+
1618
<link href="_content/Z.Blazor.Diagrams/style.min.css" rel="stylesheet" />
1719
<link href="_content/Z.Blazor.Diagrams/default.styles.min.css" rel="stylesheet" />
1820

@@ -28,6 +30,8 @@
2830
<script src="_framework/blazor.server.js"></script>
2931
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
3032

33+
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
34+
3135
<script src="_content/Z.Blazor.Diagrams/script.min.js"></script>
3236
</body>
3337
</html>

src/NodeDev.Blazor/Components/ClassExplorer.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@
204204
if (CurrentlyEditingItem.Type == TreeItemType.Method)
205205
{
206206
var method = new Core.Class.NodeClassMethod(Class, Text, Class.TypeFactory.Get(typeof(void), null), new Core.Graph());
207-
method.Graph.AddNode(new Core.Nodes.Flow.EntryNode(method.Graph));
208-
method.Graph.AddNode(new Core.Nodes.Flow.ReturnNode(method.Graph));
207+
method.Graph.AddNode(new Core.Nodes.Flow.EntryNode(method.Graph), false);
208+
method.Graph.AddNode(new Core.Nodes.Flow.ReturnNode(method.Graph), false);
209209
Class.Methods.Add(method);
210210

211211
Items.First(x => x.Type == TreeItemType.MethodsFolder).Children.Remove(CurrentlyEditingItem);

src/NodeDev.Blazor/Components/GraphCanvas.razor.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -259,11 +259,11 @@ private void OnConnectionUpdated(BaseLinkModel baseLinkModel, Anchor old, Anchor
259259
{
260260
if (source.Connection.Type.IsAssignableTo(destination.Connection.Type, out var newTypes) && newTypes.Count != 0)
261261
{
262-
PropagateNewGeneric(source.Connection.Parent, newTypes);
262+
PropagateNewGeneric(source.Connection.Parent, newTypes, false);
263263
}
264264
}
265265
else if (destination.Connection.Type is UndefinedGenericType destinationType && source.Connection.Type is not UndefinedGenericType)
266-
PropagateNewGeneric(destination.Connection.Parent, new Dictionary<UndefinedGenericType, TypeBase>() { [destinationType] = source.Connection.Type });
266+
PropagateNewGeneric(destination.Connection.Parent, new Dictionary<UndefinedGenericType, TypeBase>() { [destinationType] = source.Connection.Type }, false);
267267

268268
// we have to remove the textbox ?
269269
if (destination.Connection.Connections.Count == 1 && destination.Connection.Type.AllowTextboxEdit)
@@ -277,12 +277,14 @@ private void OnConnectionUpdated(BaseLinkModel baseLinkModel, Anchor old, Anchor
277277
if (source.Connection.Type.IsExec && source.Connection.Connections.Count > 1 && link.Target.Model is GraphPortModel target)
278278
{
279279
Diagram.Links.Remove(Diagram.Links.First(x => (x.Source.Model as GraphPortModel)?.Connection == source.Connection && (x.Target.Model as GraphPortModel)?.Connection != target.Connection));
280-
Graph.Disconnect(source.Connection, source.Connection.Connections.First(x => x != target.Connection), true);
280+
Graph.Disconnect(source.Connection, source.Connection.Connections.First(x => x != target.Connection), false);
281281
}
282282

283283
}
284284

285285
UpdateVerticesInConnection(source.Connection, destination.Connection, baseLinkModel);
286+
287+
Graph.RaiseGraphChanged(true);
286288
});
287289
}
288290

@@ -422,7 +424,7 @@ public void OnPortDroppedOnCanvas(Connection connection, global::Blazor.Diagrams
422424

423425
private void OnNewNodeTypeSelected(NodeProvider.NodeSearchResult searchResult)
424426
{
425-
var node = Graph.AddNode(searchResult);
427+
var node = Graph.AddNode(searchResult, false);
426428
node.AddDecoration(new NodeDecorationPosition(new(PopupNodePosition.X, PopupNodePosition.Y)));
427429

428430
Diagram.Batch(() =>
@@ -452,7 +454,7 @@ private void OnNewNodeTypeSelected(NodeProvider.NodeSearchResult searchResult)
452454
// if we found a connection, connect them together
453455
if (destination != null)
454456
{
455-
Graph.Connect(PopupNodeConnection, destination, true);
457+
Graph.Connect(PopupNodeConnection, destination, false);
456458

457459
if (destination.Connections.Count == 1 && destination.Type.AllowTextboxEdit)
458460
UpdateConnectionType(destination);
@@ -465,15 +467,15 @@ private void OnNewNodeTypeSelected(NodeProvider.NodeSearchResult searchResult)
465467
// check if we need to propagate some generic
466468
if (!destination.Type.IsExec && source.Type.IsAssignableTo(target.Type, out var changedGenerics))
467469
{
468-
PropagateNewGeneric(node, changedGenerics);
469-
PropagateNewGeneric(destination.Parent, changedGenerics);
470+
PropagateNewGeneric(node, changedGenerics, false);
471+
PropagateNewGeneric(destination.Parent, changedGenerics, false);
470472
}
471473
else if (source.Type.IsExec && source.Connections.Count > 1) // check if we have to disconnect the previously connected exec
472474
{
473475
Diagram.Links.Remove(Diagram.Links.First(x => (x.Source.Model as GraphPortModel)?.Connection == source && (x.Target.Model as GraphPortModel)?.Connection != target));
474476
var toRemove = source.Connections.FirstOrDefault(x => x != target);
475477
if (toRemove != null)
476-
Graph.Disconnect(source, toRemove, true);
478+
Graph.Disconnect(source, toRemove, false);
477479
}
478480
}
479481
}
@@ -482,7 +484,10 @@ private void OnNewNodeTypeSelected(NodeProvider.NodeSearchResult searchResult)
482484

483485
CreateGraphNodeModel(node);
484486
AddNodeLinks(node, false);
487+
488+
UpdateNodes(Graph.Nodes.Values.ToList());
485489
});
490+
486491
}
487492

488493
#endregion
@@ -535,14 +540,15 @@ private void OnGenericTypeSelected(TypeBase type)
535540
if (PopupNode == null || GenericTypeSelectionMenuGeneric == null)
536541
return;
537542

538-
PropagateNewGeneric(PopupNode, new Dictionary<UndefinedGenericType, TypeBase>() { [GenericTypeSelectionMenuGeneric] = type });
543+
PropagateNewGeneric(PopupNode, new Dictionary<UndefinedGenericType, TypeBase>() { [GenericTypeSelectionMenuGeneric] = type }, false);
539544

545+
// Prefer updating the nodes directly instead of calling Graph.RaiseGraphChanged(true) to be sure it is called as soon as possible
540546
UpdateNodes(Graph.Nodes.Values.ToList());
541547

542548
CancelPopup();
543549
}
544550

545-
private void PropagateNewGeneric(Node node, IReadOnlyDictionary<UndefinedGenericType, TypeBase> changedGenerics)
551+
private void PropagateNewGeneric(Node node, IReadOnlyDictionary<UndefinedGenericType, TypeBase> changedGenerics, bool requireUIRefresh)
546552
{
547553
foreach (var port in node.InputsAndOutputs) // check if any of the ports have the generic we just solved
548554
{
@@ -560,14 +566,14 @@ private void PropagateNewGeneric(Node node, IReadOnlyDictionary<UndefinedGeneric
560566
var source = isPortInput ? other : port;
561567
var target = isPortInput ? port : other;
562568
if (source.Type.IsAssignableTo(target.Type, out var changedGenerics2) && changedGenerics2.Count != 0)
563-
PropagateNewGeneric(other.Parent, changedGenerics2);
569+
PropagateNewGeneric(other.Parent, changedGenerics2, requireUIRefresh);
564570
else if ((changedGenerics2?.Count ?? 0) != 0)// damn, looks like changing the generic made it so we can't link to this connection anymore
565571
Graph.Disconnect(port, other, false); // no need to refresh UI here as it'll already be refresh at the end of this method
566572
}
567573
}
568574
}
569575

570-
Graph.RaiseGraphChanged(true);
576+
Graph.RaiseGraphChanged(requireUIRefresh);
571577
}
572578

573579
#endregion

src/NodeDev.Blazor/Components/SourceViewer.razor

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,24 @@
66
@using BlazorMonaco.Editor
77
@using BlazorMonaco.Languages
88

9-
<div class="h100 ma-2" style="width: 500px">
109

11-
@if (Method == null || Code == null)
12-
{
13-
<MudText Typo="Typo.caption">Open a method to view its generated source code</MudText>
14-
}
15-
else
16-
{
17-
var id = Code.GetHashCode().ToString();
18-
<StandaloneCodeEditor @key="id" Id="@id" ConstructionOptions="EditorConstructionOptions" CssClass="h100" />
19-
}
20-
21-
</div>
10+
@if (Method == null || Code == null)
11+
{
12+
<MudText Typo="Typo.caption">Open a method to view its generated source code</MudText>
13+
}
14+
else
15+
{
16+
var id = Code.GetHashCode().ToString();
17+
<StandaloneCodeEditor @key="id" Id="@id" ConstructionOptions="EditorConstructionOptions" CssClass="wh100" />
18+
}
2219

2320
@code {
2421
[Parameter]
2522
public NodeClassMethod? Method { get; set; }
2623

24+
[Parameter]
25+
public bool IsVisible { get; set; }
26+
2727
private NodeClassMethod? PreviousMethod { get; set; }
2828

2929
private IDisposable? GraphChangedSubscription { get; set; }
@@ -39,7 +39,6 @@
3939
ReadOnly = true,
4040
Value = Code,
4141
Language = "csharp",
42-
4342
AutomaticLayout = true
4443
};
4544
}
@@ -48,7 +47,11 @@
4847
{
4948
base.OnParametersSet();
5049

51-
if (Method != PreviousMethod)
50+
if (!IsVisible)
51+
return;
52+
53+
// Either the target method changed or it previously failed to compile
54+
if (Method != PreviousMethod || Creator == null)
5255
{
5356
if (Method?.Graph.Project != PreviousMethod?.Graph.Project)
5457
{
@@ -81,8 +84,14 @@
8184
Code = Creator.GetBodyAsCsCode(Method);
8285
StateHasChanged();
8386
}
84-
catch (Exception)
87+
catch (BuildError buildError)
8588
{
89+
Code = $"/* Error during code generation of node {buildError.Node.Name}: {System.Environment.NewLine}{buildError.Message}{System.Environment.NewLine}";
90+
91+
if(buildError.InnerException != null)
92+
Code += $"{System.Environment.NewLine}Inner exception:{System.Environment.NewLine}{buildError.InnerException}";
93+
94+
Code += $"{System.Environment.NewLine}*/";
8695
}
8796
}
8897

src/NodeDev.Blazor/Index.razor

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,48 +15,64 @@
1515
</MudAppBar>
1616
<MudMainContent Style="width: 100%; height: 100%">
1717

18-
<MudStack Row="true" Class="h100 pa-1">
18+
<MudExtensions.MudSplitter EnableSlide="true" Sensitivity="0.01" @bind-Dimension="GraphPercentage" OnDoubleClicked="@(_ => GraphPercentage = 100)" Class="h100 overflow-hidden" Style="overflow-y: hidden">
19+
<StartContent>
20+
<MudStack Row="true" Class="wh100 pa-1 relative">
1921

2022

21-
<MudTabs Elevation="2" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pa-2 h100" KeepPanelsAlive="true" Style="width: 25%; height: 100%">
22-
<MudTabPanel Text="Project">
23-
<ProjectExplorer Project="Project" @bind-SelectedClass="SelectedClass"></ProjectExplorer>
24-
</MudTabPanel>
25-
<MudTabPanel Text="Class">
26-
@if (SelectedClass != null)
27-
{
28-
<ClassExplorer @key="SelectedClass" Class="SelectedClass" SelectedMethodChanged="OpenMethod"></ClassExplorer>
29-
}
30-
</MudTabPanel>
31-
</MudTabs>
23+
<MudTabs Elevation="2" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pa-2 h100" KeepPanelsAlive="true" Style="width: 25%; height: 100%">
24+
<MudTabPanel Text="Project">
25+
<ProjectExplorer Project="Project" @bind-SelectedClass="SelectedClass"></ProjectExplorer>
26+
</MudTabPanel>
27+
<MudTabPanel Text="Class">
28+
@if (SelectedClass != null)
29+
{
30+
<ClassExplorer @key="SelectedClass" Class="SelectedClass" SelectedMethodChanged="OpenMethod"></ClassExplorer>
31+
}
32+
</MudTabPanel>
33+
</MudTabs>
3234

33-
@* The 'relative' div is used to control the "Open/Close" icon for the debugger console panel *@
34-
<div class="w100 relative flex-1">
35+
@* The 'relative' div is used to control the "Open/Close" icon for the debugger console panel as well as the source viewer open icon *@
36+
<div class="w100 relative flex-1">
3537

36-
<MudStack Row="false" Class="wh100">
38+
<MudStack Row="false" Class="wh100">
3739

38-
<DebuggedPathView OpenMethod="OpenMethodFromDebuggedPath" />
40+
<DebuggedPathView OpenMethod="OpenMethodFromDebuggedPath" />
3941

40-
<CascadingValue Value="this" IsFixed="true">
41-
<MudTabs @ref="Tabs" Elevation="2" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pa-2 wh100" KeepPanelsAlive="true" Class="wh100" @bind-ActivePanelIndex="ActivePanelIndex">
42-
@foreach (var method in OpenedMethods)
43-
{
44-
<MudTabPanel ID="method" @key="method" Text="@method.Name">
45-
<GraphCanvas @key="method.Graph" Graph="method.Graph"></GraphCanvas>
46-
</MudTabPanel>
47-
}
48-
</MudTabs>
49-
</CascadingValue>
42+
<CascadingValue Value="this" IsFixed="true">
43+
<MudTabs @ref="Tabs" Elevation="2" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pa-2 wh100" KeepPanelsAlive="true" Class="wh100" @bind-ActivePanelIndex="ActivePanelIndex">
44+
@foreach (var method in OpenedMethods)
45+
{
46+
<MudTabPanel ID="method" @key="method" Text="@method.Name">
47+
<GraphCanvas @key="method.Graph" Graph="method.Graph"></GraphCanvas>
48+
</MudTabPanel>
49+
}
50+
</MudTabs>
51+
</CascadingValue>
5052

51-
<DebuggerConsolePanel Project="Project" />
53+
<DebuggerConsolePanel Project="Project" />
54+
55+
</MudStack>
56+
57+
</div>
58+
59+
<div class="h100 absolute d-flex" style="right: 0px">
60+
@{
61+
var close = GraphPercentage <= 75;
62+
var icon = close ? Icons.Material.Filled.ArrowRight : Icons.Material.Filled.ArrowLeft;
63+
}
64+
<MudIconButton Icon="@icon" OnClick="@(() => GraphPercentage = close ? 100 : 75)" Style="margin-top: auto; margin-bottom: auto" />
65+
</div>
5266

5367
</MudStack>
5468

55-
</div>
69+
</StartContent>
5670

57-
<SourceViewer Method="@(OpenedMethods.Count > 0 ? OpenedMethods[ActivePanelIndex] : null)" />
71+
<EndContent>
72+
<SourceViewer Method="@(OpenedMethods.Count > 0 ? OpenedMethods[ActivePanelIndex] : null)" IsVisible="@(GraphPercentage != 100)" />
73+
</EndContent>
5874

59-
</MudStack>
75+
</MudExtensions.MudSplitter>
6076
</MudMainContent>
6177
</MudLayout>
6278

@@ -72,6 +88,8 @@
7288

7389
private int ActivePanelIndex = 0;
7490

91+
private double GraphPercentage = 100;
92+
7593
protected override void OnInitialized()
7694
{
7795
if (File.Exists("project.json"))

src/NodeDev.Blazor/NodeDev.Blazor.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
<ItemGroup>
1414
<PackageReference Include="BlazorMonaco" Version="3.2.0" />
15+
<PackageReference Include="CodeBeam.MudBlazor.Extensions" Version="6.9.2" />
1516
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.6" />
1617
<PackageReference Include="MudBlazor" Version="6.21.0" />
1718
</ItemGroup>

src/NodeDev.Core/BuildError.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using NodeDev.Core.Nodes;
2+
3+
namespace NodeDev.Core;
4+
5+
public class BuildError : Exception
6+
{
7+
public readonly Node Node;
8+
9+
public BuildError(string message, Node node, Exception? inner) : base(message, inner)
10+
{
11+
Node = node;
12+
}
13+
}

0 commit comments

Comments
 (0)