using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.WPF; using Expression = System.Linq.Expressions.Expression; namespace InABox.DynamicGrid; public interface IDynamicDataGrid : IDynamicGrid { /// /// The tag the the DynamicGridColumns are stored against. If set to , /// the name of is used as a default. /// string? ColumnsTag { get; set; } } public class DynamicDataGrid : DynamicGrid, IDynamicDataGrid where TEntity : Entity, IRemotable, IPersistent, new() { private Button MergeBtn = null!; //Late-initialised protected DynamicGridCustomColumnsComponent ColumnsComponent; public DynamicGridFilterButtonComponent FilterComponent; public DynamicDataGrid() : base() { var fields = DatabaseSchema.Properties(typeof(TEntity)); foreach (var field in fields) if (!MasterColumns.Any(x => x.ColumnName == field.Name)) MasterColumns.Add(new DynamicGridColumn { ColumnName = field.Name }); var cols = LookupFactory.DefineColumns(); // Minimum Columns for Lookup values foreach (var col in cols) HiddenColumns.Add(CoreUtils.CreateLambdaExpression(col.Property)); // Minimum Columns for Successful Saving // This should be cross-checked with the relevant Store<> // so that clients will (usually) provide sufficient columns for saving foreach (var col in LookupFactory.RequiredColumns()) HiddenColumns.Add(CoreUtils.CreateLambdaExpression(col.Property)); //HiddenColumns.Add(x => x.ID); if (typeof(TEntity).GetInterfaces().Contains(typeof(IIssues))) { HiddenColumns.Add(x => (x as IIssues)!.Issues); var coltype = typeof(DynamicIssuesColumn<>).MakeGenericType(typeof(TEntity)); ActionColumns.Add((Activator.CreateInstance(coltype, this) as DynamicActionColumn)!); } } protected override void Init() { FilterComponent = new(this, new GlobalConfiguration(GetTag()), new UserConfiguration(GetTag())); FilterComponent.OnFilterRefresh += () => Refresh(false, true); ColumnsComponent = new DynamicGridCustomColumnsComponent(this, GetTag()); var dataComponent = new DynamicGridClientDataComponent(this); dataComponent.OnReload += DataComponent_OnReload; DataComponent = dataComponent; MergeBtn = AddButton("Merge", Wpf.Resources.merge.AsBitmapImage(Color.White), DoMerge); } public override void SelectItems(CoreRow[]? rows) { base.SelectItems(rows); MergeBtn.Visibility = Options.MultiSelect && typeof(TEntity).IsAssignableTo(typeof(IMergeable)) && Security.CanMerge() && rows != null && rows.Length > 1 ? Visibility.Visible : Visibility.Collapsed; } private void DataComponent_OnReload(object sender, Filters criteria, Columns columns, ref SortOrder? sortby) { criteria.Add(FilterComponent.GetFilter()); } protected override void OptionsChanged() { base.OptionsChanged(); FilterComponent.ShowFilterList = Options.FilterRows && !Options.HideDatabaseFilters; if (MergeBtn != null) MergeBtn.Visibility = Visibility.Collapsed; } protected override void DoReconfigure(DynamicGridOptions options) { if (Security.CanEdit()) { options.AddRows = true; options.EditRows = true; } if (Security.CanDelete()) options.DeleteRows = true; if (Security.CanImport() && typeof(TEntity).HasInterface()) options.ImportData = true; if (Security.CanExport() && typeof(TEntity).HasInterface()) options.ExportData = true; if (Security.CanMerge()) options.MultiSelect = true; } protected override void BeforeLoad(IDynamicEditorForm form, TEntity[] items) { form.ReadOnly = form.ReadOnly || !Security.CanEdit(); base.BeforeLoad(form, items); } private string? _columnsTag; public string? ColumnsTag { get => _columnsTag; set { _columnsTag = value; ColumnsComponent.Tag = GetTag(); } } protected override DynamicGridColumns LoadColumns() { return ColumnsComponent.LoadColumns(); } protected override void SaveColumns(DynamicGridColumns columns) { ColumnsComponent.SaveColumns(columns); } protected override void LoadColumnsMenu(ContextMenu menu) { base.LoadColumnsMenu(menu); ColumnsComponent.LoadColumnsMenu(menu); } private string GetTag() { var tag = typeof(TEntity).Name; if (!string.IsNullOrWhiteSpace(ColumnsTag)) tag = string.Format("{0}.{1}", tag, ColumnsTag); return tag; } protected override DynamicGridSettings LoadSettings() { var tag = GetTag(); var user = Task.Run(() => new UserConfiguration(tag).Load()); user.Wait(); //var global = Task.Run(() => new GlobalConfiguration(tag).Load()); //global.Wait(); //Task.WaitAll(user, global); //var columns = user.Result.Any() ? user.Result : global.Result; return user.Result; } protected override void SaveSettings(DynamicGridSettings settings) { var tag = GetTag(); new UserConfiguration(tag).Save(settings); } #region Duplicate protected override IEnumerable LoadDuplicatorItems(CoreRow[] rows) { return rows.Select(x => x.ToObject()); } #endregion #region Merge private bool DoMerge(Button arg1, CoreRow[] arg2) { if (arg2 == null || arg2.Length <= 1) return false; var target = arg2.Last().ToObject(); return DynamicGridUtils.MergeEntities( target, arg2.ToObjects().Where(x => x.ID != target.ID).ToArray()); } #endregion }