Compare commits
2
Commits
119a4a893a
...
2c1756cef6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c1756cef6 | ||
|
|
c704bc551b |
+15
-1
@@ -9,10 +9,24 @@ internal class ActionProcessor(AonprdProcessorInput input) : AbstractEntityProce
|
||||
|
||||
public override Pf2eModel.Model.Structure.Action Object { get; } = new();
|
||||
|
||||
public override void Add() => Context.Actions.Add(Object);
|
||||
private bool _skipping = false;
|
||||
|
||||
public override void Add()
|
||||
{
|
||||
if (!_skipping)
|
||||
{
|
||||
Context.Actions.Add(Object);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
if (Input.GetRequired<string>("markdown").StartsWith("**Activate**"))
|
||||
{
|
||||
_skipping = true;
|
||||
return;
|
||||
}
|
||||
|
||||
base.Process();
|
||||
|
||||
AonprdProcessorInput.ActionStruct action = Input.ResolveActionString(
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Structure;
|
||||
|
||||
namespace Pf2eViewer.Converters;
|
||||
|
||||
internal class EntityConverter : JsonConverter
|
||||
{
|
||||
private readonly Pf2eDbContext _context = new();
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(Entity) || objectType.IsAssignableTo(typeof(IEntity));
|
||||
}
|
||||
|
||||
private Dictionary<string, object?> DictionarySerialization(object source)
|
||||
{
|
||||
Dictionary<string, object?> dictionary = [];
|
||||
|
||||
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
|
||||
{
|
||||
if (property.Attributes.OfType<JsonIgnoreAttribute>().Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
object? v = property.GetValue(source);
|
||||
dictionary.Add(property.Name, v);
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Remove("Description");
|
||||
}
|
||||
|
||||
serializer.Serialize(writer, dictionary);
|
||||
}
|
||||
|
||||
private abstract class Processor
|
||||
{
|
||||
public abstract Type Type { get; }
|
||||
|
||||
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
|
||||
)
|
||||
{
|
||||
method.Invoke(dictionary, (T)entity, converter);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
),
|
||||
new Processor<Subclass>(
|
||||
(dictionary, _, _) =>
|
||||
{
|
||||
dictionary.Remove("Group");
|
||||
}
|
||||
),
|
||||
];
|
||||
|
||||
public override bool CanRead => false;
|
||||
|
||||
public override object ReadJson(
|
||||
JsonReader reader,
|
||||
Type objectType,
|
||||
object? existingValue,
|
||||
JsonSerializer serializer
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"Unnecessary because CanRead is false. The type will skip the converter."
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
|
||||
namespace Pf2eViewer.Converters;
|
||||
|
||||
public class LocaleStringConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(LocaleString);
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
JObject result = new();
|
||||
|
||||
LocaleString str = (LocaleString)value!;
|
||||
|
||||
foreach (LocaleItem item in str)
|
||||
{
|
||||
result.Add(item.Locale.GetTypeString(), item.Value);
|
||||
}
|
||||
|
||||
result.WriteTo(writer);
|
||||
}
|
||||
|
||||
public override bool CanRead => false;
|
||||
|
||||
public override object ReadJson(
|
||||
JsonReader reader,
|
||||
Type objectType,
|
||||
object? existingValue,
|
||||
JsonSerializer serializer
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"Unnecessary because CanRead is false. The type will skip the converter."
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Enum;
|
||||
|
||||
namespace Pf2eViewer.DatabaseViewer;
|
||||
|
||||
internal class DatabaseQueryPerformer
|
||||
{
|
||||
public required EntityType Type;
|
||||
|
||||
public required int Page;
|
||||
|
||||
public required int PerPage;
|
||||
|
||||
public required string Search = "";
|
||||
|
||||
private readonly Thread _queryThread;
|
||||
|
||||
public DatabaseQueryPerformer()
|
||||
{
|
||||
_queryThread = new(PerformQuery);
|
||||
}
|
||||
|
||||
public void Query()
|
||||
{
|
||||
_queryThread.Start();
|
||||
}
|
||||
|
||||
public void Abort()
|
||||
{
|
||||
_queryThread.Interrupt();
|
||||
}
|
||||
|
||||
private void PerformQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
Pf2eDbContext dbContext = new();
|
||||
|
||||
IQueryable<Entity> query =
|
||||
Search == ""
|
||||
? dbContext.Entities.Where(e => e.Type == Type)
|
||||
:
|
||||
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||
dbContext.Entities.Where(e =>
|
||||
e.Type == Type && Pf2eDbContext.LocaleSearch(e.Name, Search)
|
||||
);
|
||||
|
||||
int count = query.Count();
|
||||
|
||||
List<Entity> entities = query.Skip((Page - 1) * PerPage).Take(PerPage).ToList();
|
||||
|
||||
DatabaseQueryResult result = new(count, entities);
|
||||
|
||||
OnQueryCompleted?.Invoke(this, result);
|
||||
}
|
||||
catch (ThreadInterruptedException)
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void DatabaseQueryPerformerDelegate(
|
||||
DatabaseQueryPerformer sender,
|
||||
DatabaseQueryResult result
|
||||
);
|
||||
public event DatabaseQueryPerformerDelegate? OnQueryCompleted;
|
||||
}
|
||||
|
||||
internal class DatabaseQueryResult(int count, ICollection<Entity> entities)
|
||||
{
|
||||
public int Count { get; } = count;
|
||||
|
||||
public ConcurrentBag<Entity> Entities { get; } = new(entities);
|
||||
}
|
||||
+48
-10
@@ -1,4 +1,4 @@
|
||||
namespace Pf2eViewer;
|
||||
namespace Pf2eViewer.DatabaseViewer;
|
||||
|
||||
partial class DatabaseViewerControl
|
||||
{
|
||||
@@ -34,10 +34,13 @@ partial class DatabaseViewerControl
|
||||
DataGridView = new DataGridView();
|
||||
DbBindingSource = new BindingSource(components);
|
||||
PagesBindingSource = new BindingSource(components);
|
||||
( BindingNavigator).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) DataGridView).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) DbBindingSource).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) PagesBindingSource).BeginInit();
|
||||
Id = new DataGridViewTextBoxColumn();
|
||||
EntityName = new DataGridViewTextBoxColumn();
|
||||
Rarity = new DataGridViewTextBoxColumn();
|
||||
(BindingNavigator).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)DataGridView).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)DbBindingSource).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)PagesBindingSource).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// BindingNavigator
|
||||
@@ -62,6 +65,8 @@ partial class DatabaseViewerControl
|
||||
SearchTextBox.PlaceholderText = "Поиск";
|
||||
SearchTextBox.Size = new Size(345, 23);
|
||||
SearchTextBox.TabIndex = 3;
|
||||
SearchTextBox.TextChanged += SearchTextBox_TextChanged;
|
||||
SearchTextBox.Leave += SearchTextBox_Leave;
|
||||
//
|
||||
// DataGridView
|
||||
//
|
||||
@@ -71,6 +76,7 @@ partial class DatabaseViewerControl
|
||||
DataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader;
|
||||
DataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders;
|
||||
DataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
DataGridView.Columns.AddRange(new DataGridViewColumn[] { Id, EntityName, Rarity });
|
||||
DataGridView.DataSource = DbBindingSource;
|
||||
DataGridView.Dock = DockStyle.Fill;
|
||||
DataGridView.Location = new Point(0, 48);
|
||||
@@ -83,6 +89,36 @@ partial class DatabaseViewerControl
|
||||
DataGridView.TabIndex = 4;
|
||||
DataGridView.RowStateChanged += DataGridView_RowStateChanged;
|
||||
//
|
||||
// Id
|
||||
//
|
||||
Id.DataPropertyName = "Id";
|
||||
Id.HeaderText = "Id";
|
||||
Id.Name = "Id";
|
||||
Id.ReadOnly = true;
|
||||
Id.Resizable = DataGridViewTriState.False;
|
||||
Id.SortMode = DataGridViewColumnSortMode.NotSortable;
|
||||
Id.Width = 5;
|
||||
//
|
||||
// EntityName
|
||||
//
|
||||
EntityName.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
|
||||
EntityName.DataPropertyName = "Name";
|
||||
EntityName.HeaderText = "Name";
|
||||
EntityName.Name = "EntityName";
|
||||
EntityName.ReadOnly = true;
|
||||
EntityName.Resizable = DataGridViewTriState.False;
|
||||
EntityName.SortMode = DataGridViewColumnSortMode.NotSortable;
|
||||
//
|
||||
// Rarity
|
||||
//
|
||||
Rarity.DataPropertyName = "Rarity";
|
||||
Rarity.HeaderText = "Rarity";
|
||||
Rarity.Name = "Rarity";
|
||||
Rarity.ReadOnly = true;
|
||||
Rarity.Resizable = DataGridViewTriState.False;
|
||||
Rarity.SortMode = DataGridViewColumnSortMode.NotSortable;
|
||||
Rarity.Width = 5;
|
||||
//
|
||||
// DatabaseViewerControl
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
@@ -92,11 +128,10 @@ partial class DatabaseViewerControl
|
||||
Controls.Add(BindingNavigator);
|
||||
Name = "DatabaseViewerControl";
|
||||
Size = new Size(345, 393);
|
||||
Load += DatabaseViewerControl_Load;
|
||||
( BindingNavigator).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) DataGridView).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) DbBindingSource).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) PagesBindingSource).EndInit();
|
||||
(BindingNavigator).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)DataGridView).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)DbBindingSource).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)PagesBindingSource).EndInit();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
@@ -107,4 +142,7 @@ partial class DatabaseViewerControl
|
||||
private DataGridView DataGridView;
|
||||
private BindingSource DbBindingSource;
|
||||
private BindingSource PagesBindingSource;
|
||||
private DataGridViewTextBoxColumn Id;
|
||||
private DataGridViewTextBoxColumn EntityName;
|
||||
private DataGridViewTextBoxColumn Rarity;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Timer = System.Windows.Forms.Timer;
|
||||
|
||||
namespace Pf2eViewer.DatabaseViewer;
|
||||
|
||||
public partial class DatabaseViewerControl : UserControl
|
||||
{
|
||||
public readonly Pf2eDbContext Context = new();
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public int PerPage
|
||||
{
|
||||
get => _perPage;
|
||||
set
|
||||
{
|
||||
_perPage = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
private int _perPage = 30;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public int Page
|
||||
{
|
||||
get => _page;
|
||||
set
|
||||
{
|
||||
_page = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
private int _page = 1;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public EntityType Type
|
||||
{
|
||||
get => _type;
|
||||
set
|
||||
{
|
||||
_page = 1;
|
||||
_type = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
private EntityType _type;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public int Count { get; private set; }
|
||||
|
||||
public int MaxPage => Convert.ToInt32(Math.Ceiling(1.0 * Count / PerPage));
|
||||
|
||||
[AllowNull]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public EntityView CurrentEntity { get; private set; }
|
||||
|
||||
private bool _isBusy = true;
|
||||
|
||||
private DatabaseQueryPerformer? _performer;
|
||||
|
||||
private Timer? _typingTimer;
|
||||
|
||||
private string _lastSearch = "";
|
||||
|
||||
public DatabaseViewerControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
BindingNavigator.BindingSource = DbBindingSource;
|
||||
//DataGridView.AutoGenerateColumns = true;
|
||||
DataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||
|
||||
_isBusy = false;
|
||||
}
|
||||
|
||||
// Control events
|
||||
|
||||
private void BindingNavigator_RefreshItems(object sender, EventArgs e)
|
||||
{
|
||||
if (_isBusy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Page = (int)(BindingNavigator?.BindingSource?.Current ?? 1);
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void DataGridView_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
|
||||
{
|
||||
if (_isBusy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateEntity();
|
||||
}
|
||||
|
||||
private void SearchTextBox_Leave(object sender, EventArgs e)
|
||||
{
|
||||
if (_isBusy || SearchTextBox.Text == _lastSearch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void SearchTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_isBusy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_typingTimer == null)
|
||||
{
|
||||
_typingTimer = new();
|
||||
_typingTimer.Interval = 3000;
|
||||
_typingTimer.Tick += HandleTypingTimerTimeout;
|
||||
}
|
||||
_typingTimer.Stop(); // Resets the timer
|
||||
_typingTimer.Tag = (sender as TextBox)!.Text; // This should be done with EventArgs
|
||||
_typingTimer.Start();
|
||||
}
|
||||
|
||||
private void HandleTypingTimerTimeout(object? sender, EventArgs e)
|
||||
{
|
||||
if (_isBusy || sender is not Timer timer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateView();
|
||||
timer.Stop();
|
||||
}
|
||||
|
||||
// Updater
|
||||
|
||||
private void SetBusyStatus(bool busy)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(SetBusyStatus, busy);
|
||||
return;
|
||||
}
|
||||
|
||||
_isBusy = busy;
|
||||
|
||||
BindingNavigator.Enabled = !busy;
|
||||
DataGridView.Enabled = !busy;
|
||||
SearchTextBox.Enabled = !busy;
|
||||
|
||||
DataGridView.ColumnHeadersHeightSizeMode = !busy
|
||||
? DataGridViewColumnHeadersHeightSizeMode.AutoSize
|
||||
: DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
|
||||
}
|
||||
|
||||
public void UpdateView(bool force = false)
|
||||
{
|
||||
if (_isBusy && !force)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetBusyStatus(true);
|
||||
|
||||
_performer?.Abort();
|
||||
|
||||
_performer = new()
|
||||
{
|
||||
Type = Type,
|
||||
Page = Page,
|
||||
PerPage = PerPage,
|
||||
Search = SearchTextBox.Text,
|
||||
};
|
||||
|
||||
_performer.OnQueryCompleted += HandleQueryCompleted;
|
||||
|
||||
_performer.Query();
|
||||
}
|
||||
|
||||
private void HandleQueryCompleted(DatabaseQueryPerformer sender, DatabaseQueryResult result)
|
||||
{
|
||||
if (sender != _performer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Count = result.Count;
|
||||
_lastSearch = SearchTextBox.Text;
|
||||
|
||||
InvokeControl(
|
||||
BindingNavigator,
|
||||
b =>
|
||||
{
|
||||
PagesBindingSource.DataSource = Enumerable.Range(1, MaxPage).ToList();
|
||||
b.BindingSource = PagesBindingSource;
|
||||
}
|
||||
);
|
||||
|
||||
InvokeControl(
|
||||
DataGridView,
|
||||
view =>
|
||||
{
|
||||
view.DataSource = result.Entities.Select(e => new EntityGridRow(e)).ToList();
|
||||
|
||||
SetBusyStatus(false);
|
||||
|
||||
if (view.Rows.Count > 0)
|
||||
{
|
||||
view.Rows[0].Selected = true;
|
||||
UpdateEntity();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void InvokeControl<T>(T control, Action<T> action)
|
||||
where T : Control
|
||||
{
|
||||
if (control.InvokeRequired)
|
||||
{
|
||||
control.Invoke(action, control);
|
||||
}
|
||||
else
|
||||
{
|
||||
action(control);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEntity()
|
||||
{
|
||||
if (DataGridView.SelectedRows.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EntityGridRow? data = (EntityGridRow?)DataGridView.SelectedRows[0].DataBoundItem;
|
||||
|
||||
try
|
||||
{
|
||||
CurrentEntity = data is not null ? new(Context, Type, data.Id) : null;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
EntityChange?.Invoke(CurrentEntity);
|
||||
}
|
||||
|
||||
// Output events
|
||||
|
||||
public delegate void EntityChangeHandler(EntityView newEntity);
|
||||
|
||||
public event EntityChangeHandler? EntityChange;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+6
@@ -117,6 +117,12 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="Id.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="Rarity.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="DbBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
@@ -1,148 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
|
||||
namespace Pf2eViewer;
|
||||
|
||||
public partial class DatabaseViewerControl : UserControl
|
||||
{
|
||||
public readonly Pf2eDbContext Context = new();
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public int PerPage
|
||||
{
|
||||
get => _perPage;
|
||||
set
|
||||
{
|
||||
_perPage = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
private int _perPage = 30;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public int Page
|
||||
{
|
||||
get => _page;
|
||||
set
|
||||
{
|
||||
_page = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
private int _page = 1;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public EntityType Type
|
||||
{
|
||||
get => _type;
|
||||
set
|
||||
{
|
||||
_type = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
private EntityType _type;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public int Count { get; private set; } = 0;
|
||||
|
||||
public int MaxPage => Convert.ToInt32(Math.Ceiling(1.0 * Count / PerPage));
|
||||
|
||||
[AllowNull]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public EntityView CurrentEntity { get; private set; }
|
||||
|
||||
private bool _updating = false;
|
||||
|
||||
public DatabaseViewerControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
BindingNavigator.BindingSource = DbBindingSource;
|
||||
DataGridView.AutoGenerateColumns = true;
|
||||
DataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||
}
|
||||
|
||||
private void DatabaseViewerControl_Load(object sender, EventArgs e)
|
||||
{
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void BindingNavigator_RefreshItems(object sender, EventArgs e)
|
||||
{
|
||||
if (_updating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Page = (int)(BindingNavigator?.BindingSource?.Current ?? 1);
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
public void UpdateView()
|
||||
{
|
||||
_updating = true;
|
||||
|
||||
IQueryable<Entity> query = Context.Entities.Where(e =>
|
||||
e.Type == Type
|
||||
&& (
|
||||
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
|
||||
SearchTextBox.Text == ""
|
||||
|| Pf2eDbContext.LocaleSearch(e.Name, SearchTextBox.Text)
|
||||
)
|
||||
);
|
||||
|
||||
Count = query.Count();
|
||||
|
||||
PagesBindingSource.DataSource = Enumerable.Range(1, MaxPage).ToList();
|
||||
BindingNavigator.BindingSource = PagesBindingSource;
|
||||
|
||||
DbBindingSource.DataSource = query
|
||||
.Skip((Page - 1) * PerPage)
|
||||
.Take(PerPage)
|
||||
.Select(e => new EntityGridRow(e))
|
||||
.ToList();
|
||||
|
||||
if (DataGridView.Rows.Count > 0)
|
||||
{
|
||||
DataGridView.Rows[0].Selected = true;
|
||||
}
|
||||
DataGridView.Update();
|
||||
|
||||
_updating = false;
|
||||
}
|
||||
|
||||
private void DataGridView_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
|
||||
{
|
||||
if (DataGridView.SelectedRows.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EntityGridRow data = (EntityGridRow)DataGridView.SelectedRows[0].DataBoundItem;
|
||||
CurrentEntity = new(Context, Type, data.Id);
|
||||
|
||||
EntityChange?.Invoke(CurrentEntity);
|
||||
}
|
||||
|
||||
public delegate void EntityChangeHandler(EntityView newEntity);
|
||||
|
||||
public event EntityChangeHandler? EntityChange;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -146,8 +146,8 @@ public sealed partial class EntityTreeViewerControl : UserControl
|
||||
|
||||
NameWidth = maxNameWidth + 3;
|
||||
|
||||
Debug.WriteLine($@"Height Inner {ContentWidth} / Outer {Width}");
|
||||
Debug.WriteLine($@"Name {NameWidth} / Full {ContentWidth}");
|
||||
// Debug.WriteLine($@"Height Inner {ContentWidth} / Outer {Width}");
|
||||
// Debug.WriteLine($@"Name {NameWidth} / Full {ContentWidth}");
|
||||
|
||||
foreach (EntityTreeViewerControlRow row in _viewerRows)
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ public class EntityView
|
||||
.ThenInclude(x => x.Target)
|
||||
.Include(e => e.Traits)
|
||||
.ThenInclude(t => t.Entity)
|
||||
.FirstOrDefault() ?? throw new Exception("Entity is null");
|
||||
.FirstOrDefault() ?? throw new("Entity is null");
|
||||
|
||||
IEntity? subEntity =
|
||||
(getter != null)
|
||||
|
||||
Generated
+17
-13
@@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
|
||||
using Pf2eViewer.DatabaseViewer;
|
||||
|
||||
namespace Pf2eViewer;
|
||||
|
||||
@@ -65,8 +66,8 @@ partial class MainViewForm
|
||||
//
|
||||
RootSplitContainer.Panel2.Controls.Add(ResultSplitContainer);
|
||||
RootSplitContainer.Panel2MinSize = 400;
|
||||
RootSplitContainer.Size = new Size(1181, 688);
|
||||
RootSplitContainer.SplitterDistance = 254;
|
||||
RootSplitContainer.Size = new Size(1384, 861);
|
||||
RootSplitContainer.SplitterDistance = 322;
|
||||
RootSplitContainer.TabIndex = 0;
|
||||
//
|
||||
// InnerSplitContainer
|
||||
@@ -79,8 +80,8 @@ partial class MainViewForm
|
||||
// InnerSplitContainer.Panel1
|
||||
//
|
||||
InnerSplitContainer.Panel1.Controls.Add(TypesListBox);
|
||||
InnerSplitContainer.Size = new Size(254, 688);
|
||||
InnerSplitContainer.SplitterDistance = 102;
|
||||
InnerSplitContainer.Size = new Size(322, 861);
|
||||
InnerSplitContainer.SplitterDistance = 127;
|
||||
InnerSplitContainer.TabIndex = 1;
|
||||
//
|
||||
// InnerSplitContainer.Panel2
|
||||
@@ -93,7 +94,7 @@ partial class MainViewForm
|
||||
TypesListBox.FormattingEnabled = true;
|
||||
TypesListBox.Location = new Point(0, 0);
|
||||
TypesListBox.Name = "TypesListBox";
|
||||
TypesListBox.Size = new Size(254, 102);
|
||||
TypesListBox.Size = new Size(322, 127);
|
||||
TypesListBox.TabIndex = 0;
|
||||
TypesListBox.SelectedIndexChanged += TypesListBox_SelectedIndexChanged;
|
||||
//
|
||||
@@ -117,19 +118,22 @@ partial class MainViewForm
|
||||
// ResultSplitContainer.Panel2
|
||||
//
|
||||
ResultSplitContainer.Panel2.Controls.Add(DescriptionTextBox);
|
||||
ResultSplitContainer.Size = new Size(923, 688);
|
||||
ResultSplitContainer.SplitterDistance = 382;
|
||||
ResultSplitContainer.Size = new Size(1058, 861);
|
||||
ResultSplitContainer.SplitterDistance = 582;
|
||||
ResultSplitContainer.TabIndex = 1;
|
||||
//
|
||||
// EntityTreeViewerControl
|
||||
//
|
||||
EntityTreeViewerControl.DepthSize = 20;
|
||||
EntityTreeViewerControl.AutoScroll = true;
|
||||
EntityTreeViewerControl.ButtonSize = 15;
|
||||
EntityTreeViewerControl.DepthSize = 15;
|
||||
EntityTreeViewerControl.Dock = DockStyle.Fill;
|
||||
EntityTreeViewerControl.EntityView = null;
|
||||
EntityTreeViewerControl.Font = new Font("Consolas", 9F);
|
||||
EntityTreeViewerControl.HoverColor = SystemColors.ControlDark;
|
||||
EntityTreeViewerControl.ItemHeight = 20;
|
||||
EntityTreeViewerControl.Location = new Point(0, 0);
|
||||
EntityTreeViewerControl.Name = "EntityTreeViewerControl";
|
||||
EntityTreeViewerControl.Size = new Size(382, 688);
|
||||
EntityTreeViewerControl.Size = new Size(582, 861);
|
||||
EntityTreeViewerControl.TabIndex = 0;
|
||||
//
|
||||
// DescriptionTextBox
|
||||
@@ -141,14 +145,14 @@ partial class MainViewForm
|
||||
DescriptionTextBox.Name = "DescriptionTextBox";
|
||||
DescriptionTextBox.ReadOnly = true;
|
||||
DescriptionTextBox.ScrollBars = ScrollBars.Vertical;
|
||||
DescriptionTextBox.Size = new Size(537, 688);
|
||||
DescriptionTextBox.Size = new Size(472, 861);
|
||||
DescriptionTextBox.TabIndex = 0;
|
||||
//
|
||||
// MainViewForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(1181, 688);
|
||||
ClientSize = new Size(1384, 861);
|
||||
Controls.Add(RootSplitContainer);
|
||||
Name = "MainViewForm";
|
||||
Text = "DataBaseViewer";
|
||||
@@ -174,6 +178,6 @@ partial class MainViewForm
|
||||
private ListBox TypesListBox;
|
||||
private SplitContainer ResultSplitContainer;
|
||||
private TextBox DescriptionTextBox;
|
||||
private DatabaseViewerControl DatabaseViewer;
|
||||
private EntityTreeViewer.EntityTreeViewerControl EntityTreeViewerControl;
|
||||
private DatabaseViewerControl DatabaseViewer;
|
||||
}
|
||||
|
||||
+16
-56
@@ -1,13 +1,6 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System.ComponentModel;
|
||||
using Pf2eModel;
|
||||
using Pf2eModel.Model;
|
||||
using Pf2eModel.Model.Base;
|
||||
using Pf2eModel.Model.Common.I18n;
|
||||
using Pf2eModel.Model.Enum;
|
||||
using Pf2eViewer.Converters;
|
||||
|
||||
namespace Pf2eViewer;
|
||||
|
||||
@@ -15,18 +8,21 @@ public partial class MainViewForm : Form
|
||||
{
|
||||
public Pf2eDbContext Context = new();
|
||||
|
||||
public readonly string JsonViewerHtml;
|
||||
|
||||
[AllowNull]
|
||||
public readonly EntityView Viewer = null;
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public EntityView? CurrentView
|
||||
{
|
||||
get => EntityTreeViewerControl.EntityView;
|
||||
set
|
||||
{
|
||||
EntityTreeViewerControl.EntityView = value;
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
|
||||
public MainViewForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
using StreamReader reader = new("Resources/json-viewer.html");
|
||||
JsonViewerHtml = reader.ReadToEnd();
|
||||
|
||||
DatabaseViewer.EntityChange += DatabaseViewer_EntityChange;
|
||||
|
||||
Reset();
|
||||
@@ -45,36 +41,6 @@ public partial class MainViewForm : Form
|
||||
TypesListBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
private void ToggleFreeze(bool state)
|
||||
{
|
||||
// EntityGridView.Visible = state;
|
||||
// JsonWebView.Visible = state;
|
||||
}
|
||||
|
||||
private void DatabaseViewer_EntityChange(EntityView newEntity)
|
||||
{
|
||||
JsonSerializerSettings settings = new()
|
||||
{
|
||||
Converters =
|
||||
[
|
||||
new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() },
|
||||
new EntityConverter(),
|
||||
new LocaleStringConverter(),
|
||||
],
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||
};
|
||||
|
||||
string result = JsonConvert.SerializeObject(newEntity.Entity, settings);
|
||||
string subResult = JsonConvert.SerializeObject(newEntity.SubEntity, settings);
|
||||
|
||||
string json = result[..^1] + $",\"SubEntity\":{subResult}}}";
|
||||
|
||||
EntityTreeViewerControl.EntityView = newEntity;
|
||||
// RenderJson(json);
|
||||
|
||||
DescriptionTextBox.Text = newEntity.Entity!.Description;
|
||||
}
|
||||
|
||||
private void TypesListBox_SelectedIndexChanged(object sender, EventArgs _)
|
||||
{
|
||||
if (TypesListBox.SelectedItem is null)
|
||||
@@ -82,21 +48,15 @@ public partial class MainViewForm : Form
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentView = null;
|
||||
|
||||
DatabaseViewer.Type = (EntityType)TypesListBox.SelectedItem;
|
||||
// Viewer.Page = 1;
|
||||
}
|
||||
|
||||
public void RenderJson(string json)
|
||||
private void DatabaseViewer_EntityChange(EntityView newEntity)
|
||||
{
|
||||
/*
|
||||
if (JsonWebView.CoreWebView2 == null)
|
||||
{
|
||||
JsonWebView.EnsureCoreWebView2Async();
|
||||
return;
|
||||
}
|
||||
CurrentView = newEntity;
|
||||
|
||||
string html = JsonViewerHtml.Replace("{JSON}", json);
|
||||
JsonWebView.CoreWebView2.NavigateToString(html);
|
||||
*/
|
||||
DescriptionTextBox.Text = newEntity.Entity!.Description;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,20 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Pf2eModel\Pf2eModel.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
</None>
|
||||
<None Update="Resources\json-viewer.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -18,7 +18,7 @@ internal static class Program
|
||||
Application.SetColorMode(SystemColorMode.System);
|
||||
#pragma warning restore WFO5001
|
||||
|
||||
// Application.Run(new MainViewForm() { StartPosition = FormStartPosition.CenterScreen });
|
||||
Application.Run(new TestForm() { StartPosition = FormStartPosition.CenterScreen });
|
||||
Application.Run(new MainViewForm() { StartPosition = FormStartPosition.CenterScreen });
|
||||
//Application.Run(new TestForm() { StartPosition = FormStartPosition.CenterScreen });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>JSON Viewer</title>
|
||||
<script src="https://pfau-software.de/json-viewer/dist/iife/index.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
background: black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<andypf-json-viewer indent="4"
|
||||
expanded="true"
|
||||
theme="classic-dark"
|
||||
expand-icon-type="square"
|
||||
show-data-types="false"
|
||||
show-toolbar="false"
|
||||
show-copy="false"
|
||||
show-size="true">
|
||||
{JSON}
|
||||
</andypf-json-viewer>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user