DynamicColumnGrid.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using InABox.Core;
  6. namespace InABox.DynamicGrid;
  7. public class DynamicColumnGrid : DynamicGrid<DynamicGridColumn>
  8. {
  9. public event GetAvailableColumnsEvent? OnProcessColumns;
  10. public DynamicColumnGrid()
  11. {
  12. Columns = new DynamicGridColumns();
  13. }
  14. protected override void Init()
  15. {
  16. base.Init();
  17. var column = MasterColumns.FirstOrDefault(x => string.Equals(x.ColumnName, nameof(DynamicGridColumn.ColumnName)));
  18. if(column is not null && column.Editor is DynamicColumnNameEditor edit)
  19. {
  20. edit.ColumnNames = () => ProcessColumns().Select(x => x.ColumnName).ToArray();
  21. }
  22. }
  23. protected override void DoReconfigure(DynamicGridOptions options)
  24. {
  25. base.DoReconfigure(options);
  26. options.RecordCount = true;
  27. options.MultiSelect = true;
  28. options.AddRows = true;
  29. options.EditRows = true;
  30. options.DeleteRows = true;
  31. options.ReorderRows = true;
  32. }
  33. private Type _type;
  34. public Type Type
  35. {
  36. get => _type;
  37. set
  38. {
  39. _type = value;
  40. var column = MasterColumns.FirstOrDefault(x => string.Equals(x.ColumnName, nameof(DynamicGridColumn.ColumnName)));
  41. if(column is not null && column.Editor is DynamicColumnNameEditor edit)
  42. {
  43. edit.Type = value;
  44. }
  45. }
  46. }
  47. public DynamicGridColumns Columns { get; }
  48. public bool DirectEdit { get; set; }
  49. protected override void MoveRows(CoreRow[] rows, int index, bool isCopy)
  50. {
  51. var targetCol = index < Columns.Count ? Columns[index] : null;
  52. var cols = LoadItems(rows);
  53. if (isCopy)
  54. {
  55. cols = cols.ToArray(x => x.Copy());
  56. }
  57. else
  58. {
  59. foreach(var col in cols)
  60. {
  61. Columns.Remove(col);
  62. }
  63. }
  64. if(targetCol is not null)
  65. {
  66. var idx = Columns.IndexOf(targetCol);
  67. Columns.InsertRange(idx, cols);
  68. }
  69. else
  70. {
  71. Columns.AddRange(cols);
  72. }
  73. Refresh(false, true);
  74. SelectedRows = cols.Select(x => Columns.IndexOf(x)).Select(x => Data.Rows[x]).ToArray();
  75. }
  76. protected override void DoAdd(bool openEditorOnDirectEdit = false)
  77. {
  78. if(DynamicGridColumnNameSelectorGrid.SelectColumnName(Type, ProcessColumns().Select(x => x.ColumnName).ToArray(), out var column))
  79. {
  80. var item = DynamicGridColumn.FromCoreGridColumn(DefaultColumns.GetColumn(Type, column));
  81. SaveItem(item);
  82. DoChanged();
  83. Refresh(false, true);
  84. }
  85. }
  86. protected override void DoValidate(DynamicGridColumn[] items, List<string> errors)
  87. {
  88. base.DoValidate(items, errors);
  89. if (items.Any(x => string.IsNullOrWhiteSpace(x.ColumnName)))
  90. errors.Add("[ColumnName] must not be blank!");
  91. }
  92. protected override Dictionary<string, object?> EditorValueChanged(IDynamicEditorForm editor, DynamicGridColumn[] items, string name, object value)
  93. {
  94. var changes = base.EditorValueChanged(editor, items, name, value);
  95. if(name == nameof(DynamicGridColumn.ColumnName) && value is string columnName)
  96. {
  97. var newCol = DynamicGridColumn.FromCoreGridColumn(DefaultColumns.GetColumn(Type, columnName));
  98. foreach(var item in items)
  99. {
  100. CoreUtils.MonitorChanges(item, () =>
  101. {
  102. item.Width = newCol.Width;
  103. item.Alignment = newCol.Alignment;
  104. item.Format = newCol.Format;
  105. item.Editor = newCol.Editor.CloneEditor();
  106. item.Caption = newCol.Caption;
  107. }, changes);
  108. }
  109. }
  110. return changes;
  111. }
  112. private IEnumerable<DynamicGridColumn> ProcessColumns()
  113. {
  114. var result = new List<DynamicGridColumn>();
  115. var cols = new DynamicGridColumns();
  116. cols.ExtractColumns(Type);
  117. foreach (var col in cols)
  118. {
  119. if (col.Editor == null)
  120. continue;
  121. if (col.Editor is NullEditor)
  122. continue;
  123. if (col.Editor.Visible != Visible.Hidden)
  124. {
  125. result.Add(col);
  126. continue;
  127. }
  128. if (!DirectEdit)
  129. continue;
  130. if (col.Editor.Editable.IsEditable() && col.ColumnName.Split('.').Length <= 2)
  131. result.Add(col);
  132. }
  133. result.Sort((a, b) => a.ColumnName.CompareTo(b.ColumnName));
  134. var args = new GetAvailableColumnsEventArgs(result);
  135. OnProcessColumns?.Invoke(args);
  136. return args.Columns;
  137. }
  138. protected override void DefineLookups(ILookupEditorControl sender, DynamicGridColumn[] items, bool async = true)
  139. {
  140. if (Type != null && sender.ColumnName.Equals("ColumnName"))
  141. {
  142. var results = new CoreTable();
  143. results.Columns.Add(new CoreColumn { ColumnName = sender.ColumnName, DataType = typeof(string) });
  144. results.Columns.Add(new CoreColumn { ColumnName = "Display", DataType = typeof(string) });
  145. var cols = ProcessColumns();
  146. foreach (var col in cols)
  147. {
  148. var row = results.NewRow();
  149. row[sender.ColumnName] = col.ColumnName;
  150. row["Display"] = col.ColumnName;
  151. results.Rows.Add(row);
  152. }
  153. sender.LoadLookups(results);
  154. }
  155. else
  156. {
  157. base.DefineLookups(sender, items, async);
  158. }
  159. }
  160. #region Save / Load
  161. protected override void Reload(
  162. Filters<DynamicGridColumn> criteria, Columns<DynamicGridColumn> columns, ref SortOrder<DynamicGridColumn>? sort,
  163. CancellationToken token, Action<CoreTable, Exception?> action)
  164. {
  165. var result = new CoreTable();
  166. if (columns == null || columns.Count == 0)
  167. result.LoadColumns(typeof(DynamicGridColumn));
  168. else
  169. result.LoadColumns(columns);
  170. result.LoadRows(Columns);
  171. action.Invoke(result, null);
  172. }
  173. public override DynamicGridColumn LoadItem(CoreRow row)
  174. {
  175. var index = Data.Rows.IndexOf(row);
  176. return Columns[index];
  177. }
  178. public override void SaveItem(DynamicGridColumn item)
  179. {
  180. try
  181. {
  182. var prop = DatabaseSchema.Property(Type, item.ColumnName);
  183. item.Editor = prop.Editor;
  184. }
  185. catch (Exception e)
  186. {
  187. Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
  188. }
  189. if (!Columns.Contains(item))
  190. Columns.Add(item);
  191. }
  192. public override void DeleteItems(params CoreRow[] rows)
  193. {
  194. foreach (var row in rows.OrderByDescending(x => x.Index))
  195. Columns.RemoveAt(row.Index);
  196. }
  197. #endregion
  198. }