using System;
using System.Collections.Generic;
using System.Linq;
using InABox.Clients;
using InABox.Core;
namespace InABox.DynamicGrid
{
public interface IDynamicEditorHost
{
///
/// A list of columns which are defined for this editor; from this are loaded the additional columns for lookups. A useful default is just
/// to call , if a singular type for the editor is well-defined.
///
///
/// I'm still not sure whether this one is actually a good idea, but it seems to be how the editors have functioned for a while. My reasoning is that
/// if the lookup defines a column to be loaded, but it doesn't get loaded because it is not in this list, then we would have broken functionality.
///
IEnumerable Columns { get; }
///
/// Loads into all columns that start with the same prefix as ; e.g, when taking a
/// lookup defined for column EntityLink.ID, will contain all EntityLink.* except EntityLink.ID.
///
/// This essentially gives us the other columns we need to load from the database for lookups.
/// See for the canonical implementation.
///
///
/// This is dumb; we don't want it, because the presence of kinda makes it redundant.
///
/// The column to use the prefix of.
/// The dictionary into which the columns will be loaded, in the form "FieldName": "EntityLink.FieldName"
void LoadColumns(string column, Dictionary columns);
///
/// In most cases, calls , and I think this should explain what this method does. Provide a method that
/// doesn't do this if you like breaking things (or if you need to provide a filter that differs from the standard lookup; just make sure that you
/// check , and use the function if not the type you want).
///
/// The T in .
/// A filter (or , being synonymous with ).
IFilter? DefineFilter(Type type);
///
/// Trigger the loading of the lookup values; the canonical implementation calls ,
/// and calls (either sync/async) when the values are loaded.
///
/// The editor to load the lookups for.
void LoadLookups(ILookupEditorControl editor);
///
/// Get a document for a given filename.
///
///
/// The usual implementation will go through the interface.
///
/// The filename of the document.
/// The document with the right filename, or if not found.
Document? FindDocument(string filename)
{
return new Client().Load(new Filter(x => x.FileName).IsEqualTo(filename)).FirstOrDefault();
}
///
/// Get a document for a given ID.
///
///
/// The usual implementation will go through the interface.
///
/// The ID of the document.
/// The document, or if not found.
Document? GetDocument(Guid id)
{
return new Client().Load(new Filter(x => x.ID).IsEqualTo(id)).FirstOrDefault();
}
///
/// Saves a document.
///
///
/// The usual implementation will go through the interface.
///
/// The document to save.
void SaveDocument(Document document)
{
new Client().Save(document, "Updated by Editor");
}
///
/// Returns a list of the currently edited items; may be an empty array.
///
/// This should probably always be a [].
///
/// The items being edited.
object?[] GetItems();
///
/// Um... I'm really not sure; achieves the same function as - if you know what that does, good job.
///
///
/// I think you should be fine to just return .Editor, as defined by .
///
/// The column to get the editor of.
/// The editor, or if it doesn't exist.
BaseEditor? GetEditor(DynamicGridColumn column);
}
public class DefaultDynamicEditorHost : IDynamicEditorHost
where T : BaseObject
{
public virtual T[]? Items { get; set; }
public IEnumerable Columns => new DynamicGridColumns().ExtractColumns(typeof(T));
public virtual IFilter? DefineFilter(Type type) => LookupFactory.DefineFilter(Items ?? Enumerable.Empty