Большой рефактор
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model;
|
||||
using Pf2eModel.Model.Base;
|
||||
@@ -39,64 +37,86 @@ internal class EntityConverter : JsonConverter
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
Dictionary<string, object?> dictionary = DictionarySerialization(value!);
|
||||
if (value == null)
|
||||
{
|
||||
serializer.Serialize(writer, null);
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<string, object?> dictionary = DictionarySerialization(value);
|
||||
|
||||
if (value.GetType() != typeof(Entity))
|
||||
{
|
||||
dictionary.Remove("Entity");
|
||||
|
||||
Processor? processor = _processors.FirstOrDefault(p => p.Type == value.GetType());
|
||||
|
||||
processor?.Process(dictionary, (IEntity)value, this);
|
||||
}
|
||||
|
||||
switch (value)
|
||||
else
|
||||
{
|
||||
case Entity entity:
|
||||
ProcessEntity(dictionary, entity);
|
||||
break;
|
||||
|
||||
case Trait trait:
|
||||
ProcessTrait(dictionary, trait);
|
||||
break;
|
||||
dictionary.Remove("Description");
|
||||
}
|
||||
|
||||
serializer.Serialize(writer, dictionary);
|
||||
}
|
||||
|
||||
/*
|
||||
writer.WriteStartObject();
|
||||
private abstract class Processor
|
||||
{
|
||||
public abstract Type Type { get; }
|
||||
|
||||
foreach (KeyValuePair<string, object> keyValuePair in dictionary)
|
||||
public abstract void Process(
|
||||
Dictionary<string, object?> dictionary,
|
||||
IEntity entity,
|
||||
EntityConverter converter
|
||||
);
|
||||
}
|
||||
|
||||
private class Processor<T>(Action<Dictionary<string, object?>, T, EntityConverter> method)
|
||||
: Processor
|
||||
where T : IEntity
|
||||
{
|
||||
public override Type Type { get; } = typeof(T);
|
||||
|
||||
public override void Process(
|
||||
Dictionary<string, object?> dictionary,
|
||||
IEntity entity,
|
||||
EntityConverter converter
|
||||
)
|
||||
{
|
||||
writer.WritePropertyName(keyValuePair.Key, true);
|
||||
|
||||
serializer.Serialize(writer, keyValuePair.Value);
|
||||
method.Invoke(dictionary, (T)entity, converter);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
*/
|
||||
}
|
||||
|
||||
private void ProcessTrait(Dictionary<string, object?> dictionary, Trait trait)
|
||||
{
|
||||
LocaleString name =
|
||||
trait.Entity?.Name
|
||||
?? _context.Entities.Where(e => e.Id == trait.Id).Select(e => e.Name).FirstOrDefault()!;
|
||||
private readonly ICollection<Processor> _processors =
|
||||
[
|
||||
new Processor<Trait>(
|
||||
(dictionary, trait, converter) =>
|
||||
{
|
||||
LocaleString name =
|
||||
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
|
||||
trait.Entity?.Name
|
||||
?? converter
|
||||
._context.Entities.Where(e => e.Id == trait.Id)
|
||||
.Select(e => e.Name)
|
||||
.FirstOrDefault()!;
|
||||
|
||||
dictionary.Remove("Entity");
|
||||
dictionary.Remove("Entities");
|
||||
dictionary.Add("Name", name.ToString());
|
||||
}
|
||||
|
||||
private void ProcessEntity(Dictionary<string, object?> dictionary, Entity entity)
|
||||
{
|
||||
dictionary.Remove("Description");
|
||||
}
|
||||
|
||||
private void ProcessSubclass(Dictionary<string, object?> dictionary, Subclass entity)
|
||||
{
|
||||
dictionary.Remove("Group");
|
||||
}
|
||||
dictionary.Remove("Entity");
|
||||
dictionary.Remove("Entities");
|
||||
dictionary.Add("Name", name.ToString());
|
||||
}
|
||||
),
|
||||
new Processor<Subclass>(
|
||||
(dictionary, _, _) =>
|
||||
{
|
||||
dictionary.Remove("Group");
|
||||
}
|
||||
),
|
||||
];
|
||||
|
||||
public override bool CanRead => false;
|
||||
|
||||
public override object? ReadJson(
|
||||
public override object ReadJson(
|
||||
JsonReader reader,
|
||||
Type objectType,
|
||||
object? existingValue,
|
||||
|
||||
@@ -27,7 +27,7 @@ public class LocaleStringConverter : JsonConverter
|
||||
|
||||
public override bool CanRead => false;
|
||||
|
||||
public override object? ReadJson(
|
||||
public override object ReadJson(
|
||||
JsonReader reader,
|
||||
Type objectType,
|
||||
object? existingValue,
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Win32;
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
#pragma warning disable CS0184 // 'is' expression's given expression is never of the provided type
|
||||
#pragma warning disable CA1806
|
||||
#pragma warning disable CS8605 // Unboxing a possibly null value.
|
||||
#pragma warning disable CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes).
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
#pragma warning disable CS0169 // Field is never used
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||
|
||||
// ReSharper disable All
|
||||
|
||||
namespace Pf2eViewer;
|
||||
|
||||
@@ -1088,8 +1095,9 @@ public class DarkModeCS
|
||||
|
||||
/// <summary>Returns Windows's System Colors for UI components following Google Material Design concepts.</summary>
|
||||
/// <param name="Window">[OPTIONAL] Applies DarkMode (if set) to this Window Title and Background.</param>
|
||||
/// <param name="ColorMode">O: DarkMode, 1: LightMode</param>
|
||||
/// <returns>List of Colors: Background, OnBackground, Surface, OnSurface, Primary, OnPrimary, Secondary, OnSecondary</returns>
|
||||
public static OSThemeColors GetSystemColors(Form Window = null, int ColorMode = 0) //<- O: DarkMode, 1: LightMode
|
||||
public static OSThemeColors GetSystemColors(Form Window = null, int ColorMode = 0)
|
||||
{
|
||||
OSThemeColors _ret = new OSThemeColors();
|
||||
|
||||
@@ -1287,6 +1295,7 @@ public class DarkModeCS
|
||||
|
||||
/// <summary>Attemps to apply Window's Dark Style to the Control and all its childs.</summary>
|
||||
/// <param name="control"></param>
|
||||
/// <param name="IsDarkMode"></param>
|
||||
private static void ApplySystemDarkTheme(Control control = null, bool IsDarkMode = true)
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
using LinqToDB.SqlQuery;
|
||||
using LinqToDB.Tools;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eViewer;
|
||||
|
||||
public class DatabaseViewer
|
||||
{
|
||||
public readonly Pf2eDbContext Context = new();
|
||||
|
||||
private int _perPage = 30;
|
||||
|
||||
private int _page = 1;
|
||||
|
||||
private EntityType _entityType;
|
||||
|
||||
public int PerPage
|
||||
{
|
||||
get => _perPage;
|
||||
set
|
||||
{
|
||||
_perPage = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
|
||||
public int Page
|
||||
{
|
||||
get => _page;
|
||||
set
|
||||
{
|
||||
_page = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
|
||||
public EntityType EntityType
|
||||
{
|
||||
get => _entityType;
|
||||
set
|
||||
{
|
||||
_entityType = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
|
||||
public int Count { get; private set; }
|
||||
|
||||
public int MaxPage => Convert.ToInt32(Math.Ceiling(1.0 * Count / PerPage));
|
||||
|
||||
public ICollection<Entity> Entities { get; private set; } = [];
|
||||
|
||||
public delegate void ViewUpdateHandler();
|
||||
public event ViewUpdateHandler? ViewUpdateStart;
|
||||
public event ViewUpdateHandler? ViewUpdate;
|
||||
|
||||
public Entity? LastEntity;
|
||||
public IEntity? LastSubEntity;
|
||||
|
||||
public delegate void ViewSelectHandler(Entity? entity, IEntity? subEntity);
|
||||
public event ViewSelectHandler? ViewSelect;
|
||||
|
||||
public void UpdateView()
|
||||
{
|
||||
ViewUpdateStart?.Invoke();
|
||||
|
||||
Count = Context.Entities.Count(e => e.Type == EntityType);
|
||||
|
||||
if (_page < 1 || _page > MaxPage)
|
||||
{
|
||||
_page = Math.Min(MaxPage, Math.Max(1, _page));
|
||||
}
|
||||
|
||||
Entities = Context
|
||||
.Entities.Where(e => e.Type == EntityType)
|
||||
.OrderBy(e => e.Id)
|
||||
.Skip((Page - 1) * PerPage)
|
||||
.Take(PerPage)
|
||||
.ToList();
|
||||
|
||||
ViewUpdate?.Invoke();
|
||||
}
|
||||
|
||||
public void Select(Entity entity)
|
||||
{
|
||||
Getter? getter = _getters.FirstOrDefault(g => g.Type == entity.Type);
|
||||
|
||||
Entity? fullEntity = Context
|
||||
.Entities.Where(e => e.Id == entity.Id && e.Type == entity.Type)
|
||||
.Include(e => e.Sources)
|
||||
.ThenInclude(s => s.Source)
|
||||
.Include(e => e.Keywords)
|
||||
.Include(e => e.Externals)
|
||||
.ThenInclude(x => x.Target)
|
||||
.Include(e => e.Traits)
|
||||
.ThenInclude(t => t.Entity)
|
||||
.FirstOrDefault();
|
||||
|
||||
IEntity? subEntity =
|
||||
(getter != null)
|
||||
? getter.Get(entity.Id, Context)
|
||||
: (IEntity?)Context.Find(EntityOfTypeAttribute.Resolve(entity), entity.Id);
|
||||
|
||||
ViewSelect?.Invoke(fullEntity, subEntity);
|
||||
|
||||
LastEntity = fullEntity;
|
||||
LastSubEntity = subEntity;
|
||||
}
|
||||
|
||||
private readonly ICollection<Getter> _getters =
|
||||
[
|
||||
new Getter<Ancestry>(
|
||||
EntityType.Ancestry,
|
||||
context => context.Ancestries.Include(a => a.AncestryBoosts)
|
||||
),
|
||||
new Getter<Archetype>(
|
||||
EntityType.Archetype,
|
||||
context =>
|
||||
context
|
||||
.Archetypes.Include(a => a.DedicationFeat)
|
||||
.ThenInclude(f => f.Entity)
|
||||
.Include(a => a.Feats)
|
||||
.ThenInclude(f => f.Entity)
|
||||
),
|
||||
new Getter<Background>(
|
||||
EntityType.Background,
|
||||
context =>
|
||||
context
|
||||
.Backgrounds.Include(b => b.BackgroundBoosts)
|
||||
.Include(b => b.BackgroundSkills)
|
||||
.ThenInclude(t => t.Training)
|
||||
.Include(b => b.BackgroundItems)
|
||||
),
|
||||
new Getter<Class>(
|
||||
EntityType.Class,
|
||||
context =>
|
||||
context
|
||||
.Classes.Include(c => c.ClassKeyAbilities)
|
||||
.Include(c => c.ClassTrainings)
|
||||
.ThenInclude(t => t.Training)
|
||||
.Include(c => c.ClassProgressions)
|
||||
),
|
||||
new Getter<Feat>(
|
||||
EntityType.Feat,
|
||||
context =>
|
||||
context.Feats.Include(f => f.Archetypes).ThenInclude(a => a.Entity).AsQueryable()
|
||||
),
|
||||
];
|
||||
|
||||
private abstract class Getter(EntityType type)
|
||||
{
|
||||
public readonly EntityType Type = type;
|
||||
|
||||
public abstract IEntity? Get(int id, Pf2eDbContext context);
|
||||
}
|
||||
|
||||
private class Getter<T>(EntityType type, Func<Pf2eDbContext, IQueryable<T>> method)
|
||||
: Getter(type)
|
||||
where T : IEntity
|
||||
{
|
||||
public override IEntity? Get(int id, Pf2eDbContext context)
|
||||
{
|
||||
return method.Invoke(context).FirstOrDefault(c => c.Id == id);
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
-226
@@ -1,7 +1,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model;
|
||||
@@ -9,6 +9,7 @@ using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eViewer.Converters;
|
||||
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
||||
|
||||
namespace Pf2eViewer;
|
||||
|
||||
@@ -16,15 +17,15 @@ public partial class MainViewForm : Form
|
||||
{
|
||||
public Pf2eDbContext Context = new();
|
||||
|
||||
public string JsonViewerHtml = string.Empty;
|
||||
public readonly string JsonViewerHtml;
|
||||
|
||||
private DarkModeCS dm = null;
|
||||
public readonly DatabaseViewer Viewer = new();
|
||||
|
||||
public MainViewForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
dm = new DarkModeCS(this) { ColorMode = DarkModeCS.DisplayMode.SystemDefault };
|
||||
_ = new DarkModeCS(this) { ColorMode = DarkModeCS.DisplayMode.SystemDefault };
|
||||
|
||||
Reset();
|
||||
|
||||
@@ -32,6 +33,10 @@ public partial class MainViewForm : Form
|
||||
|
||||
using StreamReader reader = new("Resources/json-viewer.html");
|
||||
JsonViewerHtml = reader.ReadToEnd();
|
||||
|
||||
Viewer.ViewUpdateStart += Viewer_ViewUpdateStart;
|
||||
Viewer.ViewUpdate += Viewer_ViewUpdate;
|
||||
Viewer.ViewSelect += Viewer_ViewSelect;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
@@ -43,53 +48,63 @@ public partial class MainViewForm : Form
|
||||
TypesListBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
public const int PerPage = 30;
|
||||
|
||||
public int Count;
|
||||
|
||||
public int Page
|
||||
private void ToggleFreeze(bool state)
|
||||
{
|
||||
get => Convert.ToInt32(PageTextBox.Text);
|
||||
set
|
||||
{
|
||||
PageTextBox.Text = value.ToString();
|
||||
UpdateTreeView();
|
||||
}
|
||||
EntityGridView.Visible = state;
|
||||
JsonWebView.Visible = state;
|
||||
|
||||
FirstPageButton.Enabled = state;
|
||||
PrevPageButton.Enabled = state;
|
||||
NextPageButton.Enabled = state;
|
||||
LastPageButton.Enabled = state;
|
||||
|
||||
PageTextBox.Enabled = state;
|
||||
}
|
||||
|
||||
public int MaxPage => Convert.ToInt32(Math.Ceiling(1.0 * Count / PerPage));
|
||||
// Viewer events
|
||||
|
||||
private void UpdateTreeView()
|
||||
private void Viewer_ViewUpdateStart()
|
||||
{
|
||||
// EntityTreeView.Nodes.Clear();
|
||||
EntityType type = (EntityType)TypesListBox.SelectedItem!;
|
||||
|
||||
Count = Context.Entities.Count(e => e.Type == type);
|
||||
|
||||
if (Page < 1 || Page > MaxPage)
|
||||
{
|
||||
Page = Math.Min(MaxPage, Math.Max(1, Page));
|
||||
return;
|
||||
}
|
||||
|
||||
EntityGridView.DataSource = Context
|
||||
.Entities.Where(e => e.Type == (EntityType)TypesListBox.SelectedItem)
|
||||
.OrderBy(e => e.Id)
|
||||
.Select(e => new EntityGridRow(e))
|
||||
.Skip((Page - 1) * PerPage)
|
||||
.Take(PerPage)
|
||||
.ToList();
|
||||
|
||||
EntityGridView.Rows[0].Selected = true;
|
||||
|
||||
PaginationLabel.Text = $"Всего: {Count} объектов, {MaxPage} страниц";
|
||||
|
||||
FirstPageButton.Enabled = Page > 1;
|
||||
PrevPageButton.Enabled = Page > 1;
|
||||
NextPageButton.Enabled = Page < MaxPage;
|
||||
LastPageButton.Enabled = Page < MaxPage;
|
||||
ToggleFreeze(false);
|
||||
}
|
||||
|
||||
private void Viewer_ViewUpdate()
|
||||
{
|
||||
EntityGridView.DataSource = Viewer.Entities.Select(e => new EntityGridRow(e));
|
||||
|
||||
PaginationLabel.Text = $@"Всего: {Viewer.Count} объектов, {Viewer.MaxPage} страниц";
|
||||
|
||||
FirstPageButton.Enabled = Viewer.Page > 1;
|
||||
PrevPageButton.Enabled = Viewer.Page > 1;
|
||||
NextPageButton.Enabled = Viewer.Page < Viewer.MaxPage;
|
||||
LastPageButton.Enabled = Viewer.Page < Viewer.MaxPage;
|
||||
|
||||
ToggleFreeze(true);
|
||||
}
|
||||
|
||||
private void Viewer_ViewSelect(Entity? entity, IEntity? subEntity)
|
||||
{
|
||||
JsonSerializerSettings settings = new()
|
||||
{
|
||||
Converters =
|
||||
[
|
||||
new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() },
|
||||
new EntityConverter(),
|
||||
new LocaleStringConverter(),
|
||||
],
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||
};
|
||||
|
||||
string result = JsonConvert.SerializeObject(entity, settings);
|
||||
string subResult = JsonConvert.SerializeObject(subEntity, settings);
|
||||
|
||||
string json = result[..^1] + $",\"SubEntity\":{subResult}}}";
|
||||
|
||||
RenderJson(json);
|
||||
}
|
||||
|
||||
// Form events
|
||||
|
||||
private void TypesListBox_SelectedIndexChanged(object sender, EventArgs _)
|
||||
{
|
||||
if (TypesListBox.SelectedItem is null)
|
||||
@@ -97,27 +112,27 @@ public partial class MainViewForm : Form
|
||||
return;
|
||||
}
|
||||
|
||||
Page = 1;
|
||||
Viewer.Page = 1;
|
||||
}
|
||||
|
||||
private void FirstPageButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Page = 1;
|
||||
Viewer.Page = 1;
|
||||
}
|
||||
|
||||
private void PrevPageButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Page--;
|
||||
Viewer.Page--;
|
||||
}
|
||||
|
||||
private void NextPageButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Page++;
|
||||
Viewer.Page++;
|
||||
}
|
||||
|
||||
private void LastPageButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Page = MaxPage;
|
||||
Viewer.Page = Viewer.MaxPage;
|
||||
}
|
||||
|
||||
private void PageTextBox_KeyPress(object sender, KeyPressEventArgs e)
|
||||
@@ -129,7 +144,7 @@ public partial class MainViewForm : Form
|
||||
|
||||
if (e.KeyChar == (char)Keys.Return)
|
||||
{
|
||||
UpdateTreeView();
|
||||
Viewer.Page = Convert.ToInt32(PageTextBox.Text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,37 +163,7 @@ public partial class MainViewForm : Form
|
||||
|
||||
EntityGridRow data = (EntityGridRow)row.DataBoundItem;
|
||||
|
||||
ViewEntity(data.Id);
|
||||
}
|
||||
|
||||
public void ViewEntity(int id)
|
||||
{
|
||||
// EntityTreeView.Nodes.Clear();
|
||||
|
||||
Entity? entity = Context
|
||||
.Entities.Where(e => e.Id == id && e.Type == (EntityType)TypesListBox.SelectedItem!)
|
||||
.Include(e => e.Sources)
|
||||
.ThenInclude(s => s.Source)
|
||||
.Include(e => e.Keywords)
|
||||
.Include(e => e.Externals)
|
||||
.ThenInclude(x => x.Target)
|
||||
.Include(e => e.Traits)
|
||||
.ThenInclude(t => t.Entity)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
DescriptionTextBox.Text = "Not found";
|
||||
return;
|
||||
}
|
||||
|
||||
string json = SerializeEntity(entity);
|
||||
|
||||
// JsonToTreeview(EntityTreeView, json, "Entity");
|
||||
|
||||
RenderJson(json);
|
||||
|
||||
DescriptionTextBox.Text = entity.Description.Replace("\\r", "").Replace("\\n", "\\r\\n");
|
||||
Viewer.Select(data.GetEntity());
|
||||
}
|
||||
|
||||
public void RenderJson(string json)
|
||||
@@ -199,149 +184,17 @@ public partial class MainViewForm : Form
|
||||
)
|
||||
{
|
||||
JsonWebView.Visible = true;
|
||||
DataGridViewRow row = EntityGridView.SelectedRows[0];
|
||||
|
||||
EntityGridRow data = (EntityGridRow)row.DataBoundItem;
|
||||
|
||||
ViewEntity(data.Id);
|
||||
}
|
||||
|
||||
public string SerializeEntity(Entity entity)
|
||||
{
|
||||
JsonSerializerSettings settings = new()
|
||||
{
|
||||
Converters =
|
||||
[
|
||||
new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() },
|
||||
new EntityConverter(),
|
||||
new LocaleStringConverter(),
|
||||
],
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||
};
|
||||
|
||||
string result = JsonConvert.SerializeObject(entity, settings);
|
||||
|
||||
Type type = EntityOfTypeAttribute.Resolve(entity);
|
||||
string subResult = JsonConvert.SerializeObject(ResolveSubEntity(entity), settings);
|
||||
|
||||
return result[..^1] + $",\"SubEntity\":{subResult}}}";
|
||||
}
|
||||
|
||||
public IEntity? ResolveSubEntity(Entity entity)
|
||||
{
|
||||
switch (entity.Type)
|
||||
{
|
||||
case EntityType.Ancestry:
|
||||
return Context
|
||||
.Ancestries.Include(a => a.AncestryBoosts)
|
||||
.FirstOrDefault(e => e.Id == entity.Id);
|
||||
|
||||
case EntityType.Archetype:
|
||||
return Context
|
||||
.Archetypes.Include(a => a.DedicationFeat)
|
||||
.ThenInclude(f => f.Entity)
|
||||
.Include(a => a.Feats)
|
||||
.ThenInclude(f => f.Entity)
|
||||
.FirstOrDefault(a => a.Id == entity.Id);
|
||||
|
||||
case EntityType.Background:
|
||||
return Context
|
||||
.Backgrounds.Include(b => b.BackgroundBoosts)
|
||||
.Include(b => b.BackgroundSkills)
|
||||
.ThenInclude(t => t.Training)
|
||||
.Include(b => b.BackgroundItems)
|
||||
.FirstOrDefault(e => e.Id == entity.Id);
|
||||
|
||||
case EntityType.Class:
|
||||
return Context
|
||||
.Classes.Include(c => c.ClassKeyAbilities)
|
||||
.Include(c => c.ClassTrainings)
|
||||
.ThenInclude(t => t.Training)
|
||||
.Include(c => c.ClassProgressions)
|
||||
.FirstOrDefault(c => c.Id == entity.Id);
|
||||
|
||||
case EntityType.Feat:
|
||||
return Context
|
||||
.Feats.Include(f => f.Archetypes)
|
||||
.ThenInclude(a => a.Entity)
|
||||
.FirstOrDefault(f => f.Id == entity.Id);
|
||||
|
||||
default:
|
||||
Type type = EntityOfTypeAttribute.Resolve(entity);
|
||||
return (IEntity?)Context.Find(type, entity.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public static void JsonToTreeview(TreeView treeView, string jsonString, string rootName)
|
||||
{
|
||||
object json = jsonString.StartsWith('[')
|
||||
? JArray.Parse(jsonString)
|
||||
: JObject.Parse(jsonString);
|
||||
|
||||
treeView.Nodes.Clear();
|
||||
foreach (TreeNode node in Element2TreeNode(json, rootName).Nodes)
|
||||
{
|
||||
treeView.Nodes.Add(node);
|
||||
}
|
||||
treeView.ExpandAll();
|
||||
}
|
||||
|
||||
private static TreeNode Element2TreeNode(object element, string text = "")
|
||||
{
|
||||
List<TreeNode> subNodes = [];
|
||||
|
||||
switch (element.GetType().Name)
|
||||
{
|
||||
case "JObject":
|
||||
JObject jObject = (JObject)element;
|
||||
foreach (KeyValuePair<string, JToken> token in jObject)
|
||||
{
|
||||
subNodes.Add(Element2TreeNode(token.Value, token.Key));
|
||||
}
|
||||
break;
|
||||
|
||||
case "JArray":
|
||||
JArray jArray = (JArray)element;
|
||||
int i = 0;
|
||||
subNodes.AddRange(jArray.Select(token => Element2TreeNode(token, $"[{i++}]")));
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
text += ": []";
|
||||
}
|
||||
break;
|
||||
|
||||
case "JValue":
|
||||
JValue jValue = (JValue)element;
|
||||
text += $": ({jValue.Type}) {jValue}";
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception(
|
||||
"clsJSON2Treeview can't interpret object:" + element.GetType().Name
|
||||
);
|
||||
}
|
||||
|
||||
TreeNode treeNode = new(text);
|
||||
|
||||
if (subNodes.Count > 0)
|
||||
{
|
||||
treeNode.Nodes.AddRange(
|
||||
subNodes.OrderBy(node => node.Nodes.Count > 0 ? 1 : 0).ToArray()
|
||||
);
|
||||
}
|
||||
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
private class EntityGridRow(Entity e)
|
||||
{
|
||||
public int Id { get; set; } = e.Id;
|
||||
public string Name { get; set; } = e.Name[LocaleType.English];
|
||||
public EntityRarity Rarity { get; set; } = e.Rarity;
|
||||
|
||||
private readonly Entity _e = e;
|
||||
|
||||
public Entity GetEntity() => _e;
|
||||
Viewer_ViewSelect(Viewer.LastEntity, Viewer.LastSubEntity);
|
||||
}
|
||||
}
|
||||
|
||||
internal class EntityGridRow(Entity e)
|
||||
{
|
||||
public int Id { get; set; } = e.Id;
|
||||
public string Name { get; set; } = e.Name[LocaleType.English];
|
||||
public EntityRarity Rarity { get; set; } = e.Rarity;
|
||||
|
||||
private readonly Entity _e = e;
|
||||
|
||||
public Entity GetEntity() => _e;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user