Skip to content

Commit

Permalink
[Database editor] Support for conditions in database table editors
Browse files Browse the repository at this point in the history
  • Loading branch information
BAndysc committed May 8, 2021
1 parent d885c29 commit 004fde7
Show file tree
Hide file tree
Showing 16 changed files with 345 additions and 32 deletions.
Expand Up @@ -13,9 +13,12 @@ public class FieldValueTemplateSelector : IDataTemplate
{
public DataTemplate? GenericTemplate { get; set; }
public DataTemplate? BoolTemplate { get; set; }
public DataTemplate? CommandTemplate { get; set; }

public IControl Build(object param)
{
if (param is ViewModels.MultiRow.DatabaseCellViewModel vm3 && vm3.ActionCommand != null)
return CommandTemplate!.Build(param);
if ((param is DatabaseCellViewModel vm && vm.ParameterValue is ParameterValue<long> holder && holder.Parameter is BoolParameter) ||
(param is ViewModels.MultiRow.DatabaseCellViewModel vm2 && vm2.ParameterValue is ParameterValue<long> holder2 && holder2.Parameter is BoolParameter))
return BoolTemplate!.Build(param);
Expand Down
Expand Up @@ -74,6 +74,11 @@
</UserControl.Styles>
<UserControl.DataTemplates>
<helpers:FieldValueTemplateSelector>
<helpers:FieldValueTemplateSelector.CommandTemplate>
<DataTemplate>
<Button Command="{Binding ActionCommand}" CommandParameter="{Binding}" Content="{Binding ActionLabel}" />
</DataTemplate>
</helpers:FieldValueTemplateSelector.CommandTemplate>
<helpers:FieldValueTemplateSelector.BoolTemplate>
<DataTemplate>
<controls2:FastBoolCellView Height="24" Margin="0,0,10,0"
Expand Down
3 changes: 3 additions & 0 deletions WDE.DatabaseEditors.WPF/Helpers/FieldValueTemplateSelector.cs
Expand Up @@ -10,9 +10,12 @@ public class FieldValueTemplateSelector : DataTemplateSelector
{
public DataTemplate GenericTemplate { get; set; }
public DataTemplate BoolTemplate { get; set; }
public DataTemplate CommandTemplate { get; set; }

public override DataTemplate SelectTemplate(object param, DependencyObject container)
{
if (param is ViewModels.MultiRow.DatabaseCellViewModel vm3 && vm3.ActionCommand != null)
return CommandTemplate;
if ((param is DatabaseCellViewModel vm && vm.ParameterValue is ParameterValue<long> holder && holder.Parameter is BoolParameter) ||
(param is ViewModels.MultiRow.DatabaseCellViewModel vm2 && vm2.ParameterValue is ParameterValue<long> holder2 && holder2.Parameter is BoolParameter))
return BoolTemplate;
Expand Down
Expand Up @@ -54,6 +54,11 @@
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplateSelector>
<helpers:FieldValueTemplateSelector>
<helpers:FieldValueTemplateSelector.CommandTemplate>
<DataTemplate>
<Button Command="{Binding ActionCommand}" CommandParameter="{Binding}" Content="{Binding ActionLabel}" />
</DataTemplate>
</helpers:FieldValueTemplateSelector.CommandTemplate>
<helpers:FieldValueTemplateSelector.BoolTemplate>
<DataTemplate>
<controls:FastBoolCellView Height="24" Margin="0,0,10,0"
Expand Down
13 changes: 10 additions & 3 deletions WDE.DatabaseEditors/Data/DatabaseTableModelGenerator.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using WDE.Common.Database;
using WDE.Common.Services.MessageBox;
using WDE.DatabaseEditors.Data.Interfaces;
using WDE.DatabaseEditors.Data.Structs;
Expand Down Expand Up @@ -55,15 +56,16 @@ public DatabaseEntity CreateEmptyEntity(DatabaseTableDefinitionJson definition,
columns[column.DbColumnName] = databaseFieldFactory.CreateField(column.DbColumnName, valueHolder);
}

return new DatabaseEntity(false, key, columns);
return new DatabaseEntity(false, key, columns, null);
}

public IDatabaseTableData? CreateDatabaseTable(DatabaseTableDefinitionJson tableDefinition,
uint[] keys,
IList<Dictionary<string, (System.Type type, object value)>> fieldsFromDb)
{
HashSet<uint> providedKeys = new();


IList<IConditionLine>? conditions = null;
List<DatabaseEntity> rows = new();
foreach (var entity in fieldsFromDb)
{
Expand Down Expand Up @@ -112,6 +114,11 @@ public DatabaseEntity CreateEmptyEntity(DatabaseTableDefinitionJson definition,
{
valueHolder = new ValueHolder<long>(column.Value.value is DBNull ? 0 : ((bool)column.Value.value ? 1 : 0));
}
else if (column.Value.type == typeof(IList<IConditionLine>))
{
conditions = ((IList<IConditionLine>)column.Value.value);
continue;
}
else
{
throw new NotImplementedException();
Expand All @@ -129,7 +136,7 @@ public DatabaseEntity CreateEmptyEntity(DatabaseTableDefinitionJson definition,
columns[column.Key] = databaseFieldFactory.CreateField(column.Key, valueHolder);
}
if (key.HasValue)
rows.Add(new DatabaseEntity(true, key.Value, columns));
rows.Add(new DatabaseEntity(true, key.Value, columns, conditions?.ToList<ICondition>()));
}

if (!tableDefinition.IsMultiRecord)
Expand Down
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using WDE.Common.Database;
using WDE.DatabaseEditors.Data.Structs;
using WDE.DatabaseEditors.Models;
using WDE.Module.Attributes;
Expand Down
3 changes: 3 additions & 0 deletions WDE.DatabaseEditors/Data/Structs/DatabaseColumnJson.cs
Expand Up @@ -31,6 +31,9 @@ public class DatabaseColumnJson
[JsonProperty(PropertyName = "can_be_null")]
public bool CanBeNull { get; set; }

[JsonProperty(PropertyName = "is_condition")]
public bool IsConditionColumn { get; set; }

[JsonProperty(PropertyName = "preferred_width")]
public float? PreferredWidth { get; set; }
}
Expand Down
30 changes: 30 additions & 0 deletions WDE.DatabaseEditors/Data/Structs/DatabaseTableDefinitionJson.cs
Expand Up @@ -49,6 +49,9 @@ public class DatabaseTableDefinitionJson
[JsonProperty(PropertyName = "primary_key")]
public IList<string>? PrimaryKey { get; set; }

[JsonProperty(PropertyName = "conditions")]
public DatabaseConditionReferenceJson? Condition { get; set; }

[JsonProperty(PropertyName = "foreign_tables")]
public IList<DatabaseForeignTableJson>? ForeignTable { get; set; }

Expand All @@ -64,4 +67,31 @@ public class DatabaseTableDefinitionJson
[JsonIgnore]
public IDictionary<string, DatabaseForeignTableJson> ForeignTableByName { get; set; } = null!;
}

public class DatabaseConditionReferenceJson
{
[JsonProperty(PropertyName = "source_type")]
public int SourceType { get; set; }

[JsonProperty(PropertyName = "source_group")]
public string? SourceGroupColumn { get; set; }

[JsonProperty(PropertyName = "source_entry")]
public string? SourceEntryColumn { get; set; }

[JsonProperty(PropertyName = "source_id")]
public string? SourceIdColumn { get; set; }

[JsonProperty(PropertyName = "targets")]
public IList<DatabaseConditionTargetJson>? Targets { get; set; }
}

public class DatabaseConditionTargetJson
{
[JsonProperty(PropertyName = "id")]
public uint Id { get; set; }

[JsonProperty(PropertyName = "name")]
public string Name { get; set; } = "";
}
}
20 changes: 20 additions & 0 deletions WDE.DatabaseEditors/DbDefinitions/gossip_menu_option.json
Expand Up @@ -17,6 +17,21 @@
"MenuID",
"OptionID"
],
"conditions": {
"source_type": 15,
"source_group": "MenuID",
"source_entry": "OptionID",
"targets": [
{
"id": 0,
"name": "player"
},
{
"id": 1,
"name": "gossip sender"
}
]
},
"groups": [
{
"group_name": "group",
Expand Down Expand Up @@ -70,6 +85,11 @@
"db_column_name": "ActionMenuID",
"value_type": "GossipMenuParameter"
},
{
"is_condition": true,
"name": "Conditions",
"db_column_name": "conditions"
},
{
"name": "Action Poi ID",
"db_column_name": "ActionPoiID",
Expand Down
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using WDE.Common.Database;
using WDE.Common.History;
using WDE.DatabaseEditors.Models;

namespace WDE.DatabaseEditors.History
{
public class DatabaseEntityConditionsChangedHistoryAction : IHistoryAction
{
private readonly DatabaseEntity entity;
private readonly IReadOnlyList<ICondition>? oldConditions;
private readonly IReadOnlyList<ICondition>? newConditions;

public DatabaseEntityConditionsChangedHistoryAction(DatabaseEntity entity,
IReadOnlyList<ICondition>? oldConditions, IReadOnlyList<ICondition>? newConditions)
{
this.entity = entity;
this.oldConditions = oldConditions;
this.newConditions = newConditions;
}

public void Undo()
{
entity.Conditions = oldConditions;
}

public void Redo()
{
entity.Conditions = newConditions;
}

public string GetDescription()
{
return $"Entity {entity.Key} conditions changed";
}
}
}
46 changes: 45 additions & 1 deletion WDE.DatabaseEditors/Loaders/DatabaseTableDataProvider.cs
Expand Up @@ -18,16 +18,19 @@ public class DatabaseTableDataProvider : IDatabaseTableDataProvider
private readonly ITableDefinitionProvider tableDefinitionProvider;
private readonly IMySqlExecutor sqlExecutor;
private readonly IMessageBoxService messageBoxService;
private readonly IDatabaseProvider databaseProvider;
private readonly IDatabaseTableModelGenerator tableModelGenerator;

public DatabaseTableDataProvider(ITableDefinitionProvider tableDefinitionProvider,
IMySqlExecutor sqlExecutor,
IMessageBoxService messageBoxService,
IDatabaseProvider databaseProvider,
IDatabaseTableModelGenerator tableModelGenerator)
{
this.tableDefinitionProvider = tableDefinitionProvider;
this.sqlExecutor = sqlExecutor;
this.messageBoxService = messageBoxService;
this.databaseProvider = databaseProvider;
this.tableModelGenerator = tableModelGenerator;
}

Expand All @@ -37,6 +40,7 @@ private string BuildSQLQueryFromTableDefinition(in DatabaseTableDefinitionJson t
var tablePrimaryKey = tableDefinitionJson.TablePrimaryKeyColumnName;
var columns = tableDefinitionJson.Groups
.SelectMany(x => x.Fields)
.Where(x => !x.IsConditionColumn)
.Select(x => $"`{x.ForeignTable ?? tableName}`.`{x.DbColumnName}`")
.Distinct();
var names = string.Join(",", columns);
Expand All @@ -59,14 +63,54 @@ private string BuildSQLQueryFromTableDefinition(in DatabaseTableDefinitionJson t
return null;

IList<Dictionary<string, (Type, object)>>? result = null;
IDatabaseProvider.ConditionKeyMask keyMask = IDatabaseProvider.ConditionKeyMask.None;
if (definition.Condition != null)
{
if (definition.Condition.SourceEntryColumn != null)
keyMask |= IDatabaseProvider.ConditionKeyMask.SourceEntry;
if (definition.Condition.SourceGroupColumn != null)
keyMask |= IDatabaseProvider.ConditionKeyMask.SourceGroup;
if (definition.Condition.SourceIdColumn != null)
keyMask |= IDatabaseProvider.ConditionKeyMask.SourceId;
}

if (keys.Length > 0)
{
var sqlStatement = BuildSQLQueryFromTableDefinition(definition, keys);

try
{
result = await sqlExecutor.ExecuteSelectSql(sqlStatement);

if (definition.Condition != null)
{
foreach (var row in result)
{
int? sourceGroup = null, sourceEntry = null, sourceId = null;

if (definition.Condition.SourceGroupColumn != null &&
row.TryGetValue(definition.Condition.SourceGroupColumn, out var groupData) &&
int.TryParse(groupData.Item2.ToString(), out var groupInt))
sourceGroup = groupInt;

if (definition.Condition.SourceEntryColumn != null &&
row.TryGetValue(definition.Condition.SourceEntryColumn, out var entryData) &&
int.TryParse(entryData.Item2.ToString(), out var entryInt))
sourceEntry = entryInt;

if (definition.Condition.SourceIdColumn != null &&
row.TryGetValue(definition.Condition.SourceIdColumn, out var idData) &&
int.TryParse(idData.Item2.ToString(), out var idInt))
sourceId = idInt;

var conditionList = await databaseProvider.GetConditionsForAsync(keyMask,
new IDatabaseProvider.ConditionKey(definition.Condition.SourceType, sourceGroup,
sourceEntry, sourceId));
if (conditionList?.Count > 0)
{
row.Add("conditions", (typeof(IList<IConditionLine>), conditionList));
}
}
}
}
catch (IMySqlExecutor.CannotConnectToDatabaseException e)
{
Expand Down
43 changes: 39 additions & 4 deletions WDE.DatabaseEditors/Models/DatabaseEntity.cs
@@ -1,12 +1,32 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using WDE.Common.Annotations;
using WDE.Common.Database;
using WDE.Common.History;
using WDE.DatabaseEditors.History;

namespace WDE.DatabaseEditors.Models
{
public class DatabaseEntity
public class DatabaseEntity : INotifyPropertyChanged
{
public Dictionary<string, IDatabaseField> Cells { get; }


private IReadOnlyList<ICondition>? conditions;

public IReadOnlyList<ICondition>? Conditions
{
get => conditions;
set
{
var old = conditions;
conditions = value;
OnAction?.Invoke(new DatabaseEntityConditionsChangedHistoryAction(this, old, value));
OnPropertyChanged();
}
}

public IEnumerable<IDatabaseField> Fields => Cells.Values;

public event System.Action<IHistoryAction>? OnAction;
Expand All @@ -15,11 +35,12 @@ public class DatabaseEntity

public uint Key { get; }

public DatabaseEntity(bool existInDatabase, uint key, Dictionary<string, IDatabaseField> cells)
public DatabaseEntity(bool existInDatabase, uint key, Dictionary<string, IDatabaseField> cells, IReadOnlyList<ICondition>? conditions)
{
ExistInDatabase = existInDatabase;
Key = key;
Cells = cells;
Conditions = conditions;
foreach (var databaseField in Cells)
{
databaseField.Value.OnChanged += action =>
Expand All @@ -41,7 +62,21 @@ public DatabaseEntity Clone()
var fields = new Dictionary<string, IDatabaseField>();
foreach (var field in Cells)
fields[field.Key] = field.Value.Clone();
return new DatabaseEntity(ExistInDatabase, Key, fields);

return new DatabaseEntity(ExistInDatabase, Key, fields, Conditions == null ? null : CloneConditions(Conditions));
}

private IReadOnlyList<ICondition> CloneConditions(IReadOnlyList<ICondition> conditions)
{
return conditions.Select(c => new AbstractCondition(c)).ToList<ICondition>();
}

public event PropertyChangedEventHandler? PropertyChanged;

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

0 comments on commit 004fde7

Please sign in to comment.