Skip to content

Commit 8c5d1c1

Browse files
Update package versions, refactor classes, and add file persistence functionality
1 parent 200ee38 commit 8c5d1c1

13 files changed

Lines changed: 170 additions & 111 deletions

Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
<PackageVersion Include="TestableIO.System.IO.Abstractions.Wrappers" Version="22.0.14" />
5555
<PackageVersion Include="Tomlyn" Version="0.19.0" />
5656
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
57-
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
58-
<PackageVersion Include="Microsoft.SourceLink.AzureRepos.Git" Version="8.0.0" />
57+
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="10.0.102" />
58+
<PackageVersion Include="Microsoft.SourceLink.AzureRepos.Git" Version="10.0.102" />
5959
<PackageVersion Include="Polyfill" Version="9.7.6" />
6060
</ItemGroup>
6161
</Project>

Schema/Models/Schema.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ public class Schema
4949

5050
/// <summary>
5151
/// Reassociates schema classes and enums with their parent schema provider.
52+
/// Call this after deserializing a schema to re-establish parent-child relationships.
5253
/// </summary>
53-
internal void Reassociate()
54+
public void Reassociate()
5455
{
5556
foreach (SchemaClass schemaClass in ClassesInternal)
5657
{

SchemaEditor/AppData.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
// All rights reserved.
33
// Licensed under the MIT license.
44

5+
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("ktsu.Schema.Test")]
6+
57
namespace ktsu.SchemaEditor;
68

79
using System.Collections.ObjectModel;
810
using ktsu.AppDataStorage;
911
using ktsu.ImGui.App;
1012
using ktsu.Schema.Models.Names;
11-
using ktsu.StrongPaths;
13+
using ktsu.Semantics.Paths;
1214

13-
internal class AppData : AppData<AppData>
15+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "Instantiated via reflection by AppDataStorage")]
16+
internal sealed class AppData : AppData<AppData>
1417
{
1518
public AbsoluteFilePath CurrentSchemaPath { get; set; } = new();
1619
public ClassName CurrentClassName { get; set; } = new();

SchemaEditor/ButtonTree.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ namespace ktsu.SchemaEditor;
88

99
using ImGuiNET;
1010

11+
using ktsu.Extensions;
1112
using ktsu.ImGui.Styler;
1213
using ktsu.ImGui.Widgets;
1314

1415
internal class ButtonTree { }
15-
internal class ButtonTree<TItem> : ButtonTree
16+
internal sealed class ButtonTree<TItem> : ButtonTree
1617
{
17-
internal class Config
18+
internal sealed class Config
1819
{
1920
public bool Collapsible { get; set; }
2021
public Action<ImGuiWidgets.Tree>? OnTreeStart { get; set; }

SchemaEditor/GlobalSuppressions.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.

SchemaEditor/Popups.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ namespace ktsu.SchemaEditor;
88
using System.Collections.Generic;
99
using System.Text.Json.Serialization;
1010

11-
using ktsu.ImGui.Popups;
12-
using ktsu.StrongPaths;
11+
using static ktsu.ImGui.Popups.ImGuiPopups;
12+
using ktsu.Semantics.Paths;
1313

1414
using ktsu.Schema.Models.Types;
1515

16-
internal class Popups
16+
internal sealed class Popups
1717
{
1818
[JsonIgnore] private MessageOK PopupMessageOK { get; init; } = new();
1919
[JsonIgnore] private InputString PopupInputString { get; init; } = new();

SchemaEditor/SchemaEditor.cs

Lines changed: 28 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,24 @@ namespace ktsu.SchemaEditor;
1010
using System.Diagnostics;
1111
using System.Numerics;
1212

13-
using ImGuiNET;
13+
using Hexa.NET.ImGui;
1414

15+
using ktsu.Extensions;
1516
using ktsu.ImGui.App;
1617
using ktsu.ImGui.Styler;
1718
using ktsu.ImGui.Widgets;
1819
using ktsu.Schema.Models;
1920
using ktsu.Schema.Models.Names;
2021
using ktsu.Semantics.Paths;
22+
using ktsu.Semantics.Strings;
23+
24+
using SchemaTypes = ktsu.Schema.Models.Types;
2125

2226
public class SchemaEditor
2327
{
2428
public static SchemaEditor Instance { get; } = new();
2529
internal Schema? CurrentSchema { get; set; }
30+
internal AbsoluteFilePath CurrentSchemaPath { get; set; } = new();
2631
internal SchemaClass? CurrentClass { get; set; }
2732
internal DataSource? CurrentDataSource { get; set; }
2833
internal AppData Options { get; }
@@ -38,9 +43,9 @@ public class SchemaEditor
3843
private static void Main(string[] _)
3944
{
4045
string title = nameof(SchemaEditor);
41-
if (Instance.CurrentSchema is not null)
46+
if (Instance.CurrentSchema is not null && !string.IsNullOrEmpty(Instance.CurrentSchemaPath))
4247
{
43-
title += $" - {Instance.CurrentSchema.FilePath.FileName}";
48+
title += $" - {Path.GetFileName(Instance.CurrentSchemaPath)}";
4449
}
4550

4651
ImGuiApp.Start(new()
@@ -71,9 +76,10 @@ public SchemaEditor()
7176
Popups = Options.Popups;
7277

7378
// restore open schema
74-
if (Schema.TryLoad(Options.CurrentSchemaPath, out Schema? previouslyOpenSchema) && previouslyOpenSchema is not null)
79+
if (SchemaFile.TryLoad(Options.CurrentSchemaPath, out Schema? previouslyOpenSchema) && previouslyOpenSchema is not null)
7580
{
7681
CurrentSchema = previouslyOpenSchema;
82+
CurrentSchemaPath = Options.CurrentSchemaPath;
7783
CurrentClass = null;
7884
CurrentClass = CurrentSchema.GetClass(Options.CurrentClassName);
7985
}
@@ -101,7 +107,7 @@ private void DividerResized(ImGuiWidgets.DividerContainer container)
101107
//Dont call this directly, call QueueSaveOptions instead so that we can debounce the saves and avoid saving multiple times per frame or multiple frames in a row
102108
private void SaveOptionsInternal()
103109
{
104-
Options.CurrentSchemaPath = CurrentSchema?.FilePath ?? new();
110+
Options.CurrentSchemaPath = CurrentSchemaPath;
105111
Options.CurrentClassName = CurrentClass?.Name ?? new();
106112
Options.DividerStates[DividerContainerCols.Id] = DividerContainerCols.GetSizes();
107113
// Note: WindowState property access needs to be updated for the current ImGuiApp version
@@ -126,7 +132,7 @@ private void SaveOptionsIfRequired()
126132

127133
private void OnRender(float dt)
128134
{
129-
using (Theme.Color(Theme.Palette.Normal))
135+
using (Theme.FromColor(Color.Palette.Semantic.Primary))
130136
{
131137
DividerContainerCols.Tick(dt);
132138

@@ -145,6 +151,7 @@ private void ShowRightPanel(float dt)
145151
private void Reset()
146152
{
147153
CurrentSchema = null;
154+
CurrentSchemaPath = new();
148155
CurrentClass = null;
149156
}
150157

@@ -169,7 +176,7 @@ private void OnMenu()
169176

170177
ImGui.Separator();
171178

172-
string schemaFilePath = CurrentSchema?.FilePath ?? "";
179+
string schemaFilePath = CurrentSchemaPath;
173180
if (ImGui.MenuItem("Open Externally", !string.IsNullOrEmpty(schemaFilePath)))
174181
{
175182
using Process p = new();
@@ -194,9 +201,10 @@ private void Open()
194201
Popups.OpenBrowserFileOpen("Open Schema", (filePath) =>
195202
{
196203
Reset();
197-
if (Schema.TryLoad(filePath, out Schema? schema) && schema is not null)
204+
if (SchemaFile.TryLoad(filePath, out Schema? schema) && schema is not null)
198205
{
199206
CurrentSchema = schema;
207+
CurrentSchemaPath = filePath;
200208
CurrentClass = CurrentSchema?.FirstClass;
201209
QueueSaveOptions();
202210
}
@@ -209,20 +217,23 @@ private void Open()
209217

210218
private void Save()
211219
{
212-
if (string.IsNullOrEmpty(CurrentSchema?.FilePath ?? new()))
220+
if (string.IsNullOrEmpty(CurrentSchemaPath))
213221
{
214222
SaveAs();
215223
return;
216224
}
217225

218-
CurrentSchema?.Save();
226+
if (CurrentSchema is not null)
227+
{
228+
SchemaFile.TrySave(CurrentSchema, CurrentSchemaPath);
229+
}
219230
}
220231

221232
private void SaveAs()
222233
{
223234
Popups.OpenBrowserFileSave("Save Schema", (filePath) =>
224235
{
225-
CurrentSchema?.ChangeFilePath(filePath);
236+
CurrentSchemaPath = filePath;
226237
Save();
227238
QueueSaveOptions();
228239
}, "*.schema.json");
@@ -245,8 +256,8 @@ internal static bool ToggleVisibility(string key)
245256
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S3267:Loops should be simplified with \"LINQ\" expressions", Justification = "We want to separate out ImGui calls from enumerations")]
246257
public void ShowMemberConfig(Schema schema, SchemaMember schemaMember)
247258
{
248-
ArgumentNullException.ThrowIfNull(schema);
249-
ArgumentNullException.ThrowIfNull(schemaMember);
259+
Ensure.NotNull(schema);
260+
Ensure.NotNull(schemaMember);
250261

251262
if (ImGui.Button($"{schemaMember.Type.DisplayName}##Type{schemaMember.Name}", new Vector2(FieldWidth, 0)))
252263
{
@@ -259,7 +270,7 @@ public void ShowMemberConfig(Schema schema, SchemaMember schemaMember)
259270
ImGui.SetNextItemWidth(FieldWidth);
260271
string container = array.Container;
261272
ImGui.InputText($"##Container{schemaMember.Name}", ref container, 64);
262-
array.Container = (ContainerName)container;
273+
array.Container = container.As<ContainerName>();
263274

264275
if (array.ElementType is SchemaTypes.Object obj && obj.Class is not null)
265276
{
@@ -335,9 +346,9 @@ private void ShowSchemaConfig()
335346
{
336347
if (CurrentSchema is not null)
337348
{
338-
if (string.IsNullOrEmpty(CurrentSchema.FilePath))
349+
if (string.IsNullOrEmpty(CurrentSchemaPath))
339350
{
340-
using (Theme.Color(Theme.Palette.Error))
351+
using (Theme.FromColor(Color.Palette.Semantic.Error))
341352
{
342353
ImGui.TextUnformatted("Schema has not been saved. Save it before configuring relative paths.");
343354

@@ -350,78 +361,10 @@ private void ShowSchemaConfig()
350361
return;
351362
}
352363

353-
ImGui.TextUnformatted($"Schema Path: {CurrentSchema.FilePath}");
354-
355-
bool projectRootIsSet = ValidateProjectRootIsSet();
356-
ShowSetProjectRoot();
357-
bool schemaLocationIsValid = ValidateSchemaLocation();
358-
359-
if (projectRootIsSet && schemaLocationIsValid)
360-
{
361-
ImGui.TextUnformatted($"Data Path: {CurrentSchema.RelativePaths.RelativeDataSourcePath}");
362-
ImGui.SameLine();
363-
if (ImGui.Button("Set Data Path"))
364-
{
365-
Popups.OpenBrowserDirectory("Select Data Path", (path) => CurrentSchema.RelativePaths.RelativeDataSourcePath = path.RelativeTo(CurrentSchema.ProjectRootPath));
366-
}
367-
}
364+
ImGui.TextUnformatted($"Schema Path: {CurrentSchemaPath}");
368365
}
369366
}
370367

371-
private bool ValidateProjectRootIsSet()
372-
{
373-
if (string.IsNullOrEmpty(CurrentSchema?.RelativePaths.RelativeProjectRootPath))
374-
{
375-
using (Theme.Color(Theme.Palette.Warning))
376-
{
377-
ImGui.TextUnformatted("Set the path of the project's root directory.");
378-
}
379-
380-
return false;
381-
}
382-
383-
return true;
384-
}
385-
386-
private void ShowSetProjectRoot()
387-
{
388-
if (CurrentSchema is not null)
389-
{
390-
ImGui.TextUnformatted($"Project Root Path: {CurrentSchema.RelativePaths.RelativeProjectRootPath}");
391-
ImGui.SameLine();
392-
if (ImGui.Button("Set Project Root"))
393-
{
394-
Popups.OpenBrowserDirectory("Select Project Root", (path) => CurrentSchema.RelativePaths.RelativeProjectRootPath = path.RelativeTo(CurrentSchema.FilePath));
395-
}
396-
}
397-
}
398-
399-
private bool ValidateSchemaLocation()
400-
{
401-
if (CurrentSchema is not null)
402-
{
403-
AbsoluteFilePath absoluteSchemaPath = (AbsoluteFilePath)Path.GetFullPath(CurrentSchema.FilePath);
404-
AbsoluteDirectoryPath expectedProjectRoot = (AbsoluteDirectoryPath)Path.GetFullPath(CurrentSchema.FilePath.DirectoryPath / CurrentSchema.RelativePaths.RelativeProjectRootPath);
405-
RelativeFilePath expectedRelativeSchemaPath = (RelativeFilePath)absoluteSchemaPath.WeakString.RemovePrefix(expectedProjectRoot);
406-
AbsoluteFilePath expectedSchemaPath = expectedProjectRoot / expectedRelativeSchemaPath;
407-
if (Path.GetFullPath(expectedSchemaPath) != Path.GetFullPath(absoluteSchemaPath))
408-
{
409-
using (Theme.Color(Theme.Palette.Error))
410-
{
411-
ImGui.TextUnformatted("Schema appears to have been moved.");
412-
ImGui.TextUnformatted("Reset the path of the project's root directory.");
413-
}
414-
415-
ImGui.TextUnformatted($"Expected: {expectedSchemaPath}");
416-
ImGui.TextUnformatted($"Actual: {absoluteSchemaPath}");
417-
418-
return false;
419-
}
420-
}
421-
422-
return true;
423-
}
424-
425368
internal void EditClass(ClassName name) => EditClass(CurrentSchema?.GetClass(name));
426369

427370
internal void EditClass(SchemaClass? schemaClass)

SchemaEditor/SchemaEditor.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
<Sdk Name="Microsoft.NET.Sdk" />
33
<Sdk Name="ktsu.Sdk" />
44
<Sdk Name="ktsu.Sdk.App" />
5+
<PropertyGroup>
6+
<!-- Braced using statements preferred for ImGui scoping -->
7+
<NoWarn>$(NoWarn);IDE0063</NoWarn>
8+
</PropertyGroup>
59
<ItemGroup>
610
<PackageReference Include="ImGui.NET" />
711
<PackageReference Include="ktsu.AppDataStorage" />
812
<PackageReference Include="ktsu.ImGui.App" />
913
<PackageReference Include="ktsu.ImGui.Popups" />
1014
<PackageReference Include="ktsu.ImGui.Widgets" />
15+
<PackageReference Include="Microsoft.SourceLink.GitHub" />
16+
<PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" />
17+
<PackageReference Include="Polyfill" />
1118
</ItemGroup>
1219
<ItemGroup>
1320
<ProjectReference Include="..\Schema\Schema.csproj" />

0 commit comments

Comments
 (0)