DynamicEditorGrid.xaml.cs 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Markup;
  11. using System.Windows.Media;
  12. using System.Windows.Threading;
  13. using System.Xml;
  14. using InABox.Clients;
  15. using InABox.Configuration;
  16. using InABox.Core;
  17. using InABox.WPF;
  18. namespace InABox.DynamicGrid
  19. {
  20. /// <summary>
  21. /// Interaction logic for DynamicEditorGrid.xaml
  22. /// </summary>
  23. public delegate void OnUpdateOtherEditorHandler(string columnname, object value);
  24. public delegate Dictionary<string, object?> EditorValueChangedHandler(object sender, string name, object value);
  25. //public delegate Dictionary<object, object> EditorGetLookupsHandler(object sender, String column);
  26. public partial class DynamicEditorGrid : UserControl
  27. {
  28. public delegate void EditorCreatedHandler(object sender, double height, double width);
  29. public delegate Document FindDocumentEvent(string FileName);
  30. public delegate Document? GetDocumentEvent(Guid id);
  31. public delegate object GetPropertyValueHandler(object sender, string name);
  32. public delegate void SaveDocumentEvent(Document document);
  33. public delegate void SetPropertyValueHandler(object sender, string name, object value);
  34. // Column Definitions as defined by calling model
  35. private DynamicGridColumns _columns;
  36. private string _layoutname = "";
  37. private bool _loaded;
  38. private bool bChanging;
  39. // List of Changed Editor Values (used when redesigning screen)
  40. private readonly Dictionary<string, object> changes = new();
  41. private Grid CustomGrid;
  42. private DynamicTabControl Details;
  43. private Grid EditorGrid;
  44. // Active Editor List
  45. private readonly List<IDynamicEditorControl> editors = new();
  46. private readonly Dictionary<IDynamicEditorPage, DynamicTabItem> pagemap = new();
  47. //Dictionary<IDynamicEditorPage, bool> loadedpages = new Dictionary<IDynamicEditorPage, bool>();
  48. public DynamicEditorGrid()
  49. {
  50. InitializeComponent();
  51. Loaded += DynamicEditorGrid_Loaded;
  52. }
  53. //private Dictionary<String, Tuple<FrameworkElement, Object, DynamicGridColumn>> editors = new Dictionary<string, Tuple<FrameworkElement, Object, DynamicGridColumn>>();
  54. public DynamicEditorPages Pages { get; private set; }
  55. public bool PreloadPages { get; set; }
  56. public Type UnderlyingType { get; set; }
  57. public OnLoadPage OnLoadPage { get; set; }
  58. public OnSelectPage OnSelectPage { get; set; }
  59. public OnUnloadPage OnUnloadPage { get; set; }
  60. //private void UnloadEditorValues()
  61. //{
  62. // foreach (string columnname in editors.Keys)
  63. // {
  64. // bool changed = (bool)CoreUtils.GetPropertyValue(editors[columnname], "Changed");
  65. // if (changed)
  66. // {
  67. // changes[columnname] = CoreUtils.GetPropertyValue(editors[columnname], "Value");
  68. // Dictionary<string, object> othervalues = CoreUtils.GetPropertyValue(editors[columnname], "OtherValues") as Dictionary<string, object>;
  69. // foreach (var field in othervalues.Keys)
  70. // {
  71. // List<String> comps = columnname.Split('.').ToList();
  72. // comps[comps.Count - 1] = field;
  73. // String actualname = String.Join(".", comps);
  74. // changes[actualname] = othervalues[field];
  75. // }
  76. // }
  77. // }
  78. //}
  79. public bool IsCustomLayout { get; private set; }
  80. public IDynamicEditorControl FindEditor(string columnname)
  81. {
  82. return editors.FirstOrDefault(x => x.ColumnName.Equals(columnname));
  83. }
  84. public object GetPropertyValue(string columnname)
  85. {
  86. return OnGetPropertyValue?.Invoke(this, columnname);
  87. }
  88. public event EditorCreatedHandler OnEditorCreated;
  89. public event OnCustomiseColumns OnCustomiseColumns;
  90. public event OnGetEditor OnGetEditor;
  91. public event OnGridCustomiseEditor OnGridCustomiseEditor;
  92. public event OnGetEditorSequence OnGetSequence;
  93. public event GetPropertyValueHandler OnGetPropertyValue;
  94. public event SetPropertyValueHandler OnSetPropertyValue;
  95. public event EditorValueChangedHandler OnEditorValueChanged;
  96. public event OnReconfigureEditors ReconfigureEditors;
  97. public event OnDefineFilter OnDefineFilter;
  98. public event OnDefineLookup OnDefineLookups;
  99. public event OnLookupsDefined OnLookupsDefined;
  100. private void DynamicEditorGrid_Loaded(object sender, RoutedEventArgs e)
  101. {
  102. ConfigureEditors();
  103. LoadEditorValues();
  104. AddPages();
  105. DoReconfigureEditors();
  106. //MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
  107. //MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
  108. //if (Keyboard.PrimaryDevice != null)
  109. //{
  110. // if (Keyboard.PrimaryDevice.ActiveSource != null)
  111. // {
  112. // var e1 = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Tab) { RoutedEvent = Keyboard.KeyDownEvent };
  113. // InputManager.Current.ProcessInput(e1);
  114. // }
  115. //}
  116. editors.FirstOrDefault().SetFocus();
  117. _loaded = true;
  118. }
  119. public event GetDocumentEvent OnGetDocument;
  120. public event FindDocumentEvent OnFindDocument;
  121. public event SaveDocumentEvent OnSaveDocument;
  122. private void LoadLookupColumns(DynamicGridColumn column, Dictionary<string, string> othercolumns)
  123. {
  124. othercolumns.Clear();
  125. var comps = column.ColumnName.Split('.').ToList();
  126. comps.RemoveAt(comps.Count - 1);
  127. var prefix = string.Format("{0}.", string.Join(".", comps));
  128. var cols = _columns.Where(x => !x.ColumnName.Equals(column.ColumnName) && x.ColumnName.StartsWith(prefix));
  129. foreach (var col in cols)
  130. othercolumns[col.ColumnName.Replace(prefix, "")] = col.ColumnName;
  131. }
  132. private string GetCodeColumn(DynamicGridColumn column)
  133. {
  134. var comps = column.ColumnName.Split('.').ToList();
  135. comps.RemoveAt(comps.Count - 1);
  136. var prefix = string.Format("{0}.", string.Join(".", comps));
  137. var cols = _columns.Where(x => !x.ColumnName.Equals(column.ColumnName) && x.ColumnName.StartsWith(prefix));
  138. foreach (var col in cols)
  139. {
  140. var editor = OnGetEditor?.Invoke(col);
  141. if (editor is CodeEditor || editor is UniqueCodeEditor)
  142. return col.ColumnName.Split('.').Last();
  143. }
  144. return "";
  145. }
  146. private void ConfigurePopupEditor(PopupEditorControl popup, DynamicGridColumn column, PopupEditor editor)
  147. {
  148. popup.ColumnName = column.ColumnName;
  149. LoadLookupColumns(column, popup.OtherColumns);
  150. if (popup.EditorDefinition is DataLookupEditor)
  151. LoadLookupColumns(column, (popup.EditorDefinition as DataLookupEditor).OtherColumns);
  152. popup.OnUpdateOtherEditor += Lookup_OnUpdateOtherEditor;
  153. }
  154. private void ConfigureCodePopupEditor(CodePopupEditorControl popup, DynamicGridColumn column, CodePopupEditor editor)
  155. {
  156. popup.ColumnName = column.ColumnName;
  157. LoadLookupColumns(column, popup.OtherColumns);
  158. if (popup.EditorDefinition is DataLookupEditor)
  159. LoadLookupColumns(column, (popup.EditorDefinition as DataLookupEditor).OtherColumns);
  160. popup.CodeColumn = !string.IsNullOrEmpty(editor.CodeColumn) ? editor.CodeColumn : GetCodeColumn(column);
  161. popup.OnDefineFilter += (sender, type) => { return OnDefineFilter?.Invoke(sender, type); };
  162. popup.OnUpdateOtherEditor += Lookup_OnUpdateOtherEditor;
  163. }
  164. private void ConfigureLookupEditor(LookupEditorControl lookup, DynamicGridColumn column, LookupEditor editor)
  165. {
  166. if (editor.Width != int.MaxValue)
  167. lookup.Width = editor.Width;
  168. lookup.ColumnName = column.ColumnName;
  169. LoadLookupColumns(column, lookup.OtherColumns);
  170. if (lookup.EditorDefinition is DataLookupEditor)
  171. LoadLookupColumns(column, (lookup.EditorDefinition as DataLookupEditor).OtherColumns);
  172. lookup.OnUpdateOtherEditor += Lookup_OnUpdateOtherEditor;
  173. lookup.OnDefineLookups += sender => { OnDefineLookups?.Invoke(sender); };
  174. lookup.OnLookupsDefined += sender => { OnLookupsDefined?.Invoke(sender); };
  175. }
  176. private void ConfigureEnumEditor(LookupEditorControl lookup, DynamicGridColumn column, EnumLookupEditor editor)
  177. {
  178. if (editor.Width != int.MaxValue)
  179. lookup.Width = editor.Width;
  180. lookup.ColumnName = column.ColumnName;
  181. lookup.OnDefineLookups += sender => { OnDefineLookups?.Invoke(sender); };
  182. lookup.OnLookupsDefined += sender =>
  183. {
  184. //OnLookupsDefined?.Invoke(sender);
  185. };
  186. }
  187. private void ConfigureComboEditor(LookupEditorControl lookup, DynamicGridColumn column, ComboLookupEditor editor)
  188. {
  189. if (editor.Width != int.MaxValue)
  190. lookup.Width = editor.Width;
  191. lookup.ColumnName = column.ColumnName;
  192. lookup.OnDefineLookups += sender => { OnDefineLookups?.Invoke(sender); };
  193. lookup.OnLookupsDefined += sender => { OnLookupsDefined?.Invoke(sender); };
  194. }
  195. private void ConfigureCheckListEditor(CheckListBoxEditorControl checks, DynamicGridColumn column, CheckListEditor editor)
  196. {
  197. checks.Width = editor.Width;
  198. checks.ColumnName = column.ColumnName;
  199. checks.OnDefineLookups += sender => { OnDefineLookups?.Invoke(sender); };
  200. checks.OnLookupsDefined += sender => { OnLookupsDefined?.Invoke(sender); };
  201. }
  202. private void ConfigureDocumentEditor(DocumentEditorControl document, DynamicGridColumn column, BaseDocumentEditor editor)
  203. {
  204. document.ColumnName = column.ColumnName;
  205. LoadLookupColumns(column, document.OtherColumns);
  206. if (document.EditorDefinition is DataLookupEditor)
  207. LoadLookupColumns(column, (document.EditorDefinition as DataLookupEditor).OtherColumns);
  208. document.OnGetDocument += id => { return OnGetDocument?.Invoke(id); };
  209. document.OnSaveDocument += doc => { OnSaveDocument?.Invoke(doc); };
  210. document.OnFindDocument += file => { return OnFindDocument?.Invoke(file); };
  211. document.OnUpdateOtherEditor += Lookup_OnUpdateOtherEditor;
  212. document.Filter = editor.FileMask;
  213. }
  214. private void ConfigurePasswordEditor(PasswordEditorControl passwordEditorControl, DynamicGridColumn column, PasswordEditor passwordEditor)
  215. {
  216. passwordEditorControl.ViewButtonVisible = passwordEditor.ViewButtonVisible;
  217. }
  218. //private IEnumerable<BaseDynamicEditorControl> FindEditors(FrameworkElement element, DynamicGridColumn column)
  219. //{
  220. // if (element == null)
  221. // return new List<BaseDynamicEditorControl>();
  222. // if ((element is Border) && ((element as Border).Child is ScrollViewer))
  223. // return FindEditors(((element as Border).Child as ScrollViewer), column);
  224. // return element.FindVisualChildren<BaseDynamicEditorControl>().Where(x => x.ColumnName != null && x.ColumnName.Equals(column.ColumnName));
  225. //}
  226. private IEnumerable<BaseDynamicEditorControl> FindEditors(DynamicGridColumn column)
  227. {
  228. var results = new List<BaseDynamicEditorControl>();
  229. foreach (DynamicTabItem tab in Details.Items)
  230. {
  231. var border = tab.Content as Border;
  232. if (border != null)
  233. {
  234. var scroll = border.Child as ScrollViewer;
  235. if (scroll != null)
  236. {
  237. var grid = scroll.Content as Grid;
  238. if (grid != null)
  239. results.AddRange(grid.Children.OfType<BaseDynamicEditorControl>()
  240. .Where(x => string.Equals(x.ColumnName, column.ColumnName)));
  241. }
  242. }
  243. }
  244. //results.AddRange(FindEditors(tab.Content as FrameworkElement, column));
  245. return results;
  246. }
  247. private void ConfigureEditors()
  248. {
  249. if (editors.Any() && _columns != null)
  250. foreach (var column in _columns)
  251. {
  252. var editorname = column.ColumnName.Replace(".", "_");
  253. var
  254. Editors = FindEditors(
  255. column); //Details.FindVisualChildren<BaseDynamicEditorControl>().Where(x => x.ColumnName != null && x.ColumnName.Equals(column.ColumnName));
  256. foreach (var Editor in Editors)
  257. {
  258. var editor = Editor.EditorDefinition;
  259. //List<Object> parameters = editor.Parameters != null ? editor.Parameters.ToList() : new List<object>();
  260. if (Editor is LookupEditorControl)
  261. {
  262. if (editor is LookupEditor)
  263. ConfigureLookupEditor(Editor as LookupEditorControl, column, editor as LookupEditor);
  264. else if (editor is EnumLookupEditor)
  265. ConfigureEnumEditor(Editor as LookupEditorControl, column, editor as EnumLookupEditor);
  266. else if (editor is ComboLookupEditor)
  267. ConfigureComboEditor(Editor as LookupEditorControl, column, editor as ComboLookupEditor);
  268. }
  269. else if (Editor is CheckListBoxEditorControl && editor is CheckListEditor)
  270. {
  271. ConfigureCheckListEditor(Editor as CheckListBoxEditorControl, column, editor as CheckListEditor);
  272. }
  273. else if (Editor is PopupEditorControl && editor is PopupEditor)
  274. {
  275. ConfigurePopupEditor(Editor as PopupEditorControl, column, editor as PopupEditor);
  276. }
  277. else if (Editor is CodePopupEditorControl && editor is CodePopupEditor)
  278. {
  279. ConfigureCodePopupEditor(Editor as CodePopupEditorControl, column, editor as CodePopupEditor);
  280. }
  281. else if (Editor is DocumentEditorControl && editor is BaseDocumentEditor)
  282. {
  283. ConfigureDocumentEditor(Editor as DocumentEditorControl, column, editor as BaseDocumentEditor);
  284. }
  285. else if (Editor is PasswordEditorControl && editor is PasswordEditor)
  286. {
  287. ConfigurePasswordEditor(Editor as PasswordEditorControl, column, editor as PasswordEditor);
  288. }
  289. Editor.Configure();
  290. if (!editors.Any(x => x.ColumnName.Equals(Editor.ColumnName)))
  291. editors.Add(Editor);
  292. Editor.Loaded = true;
  293. }
  294. }
  295. }
  296. private bool LoadLayout(string xaml)
  297. {
  298. if (!string.IsNullOrWhiteSpace(xaml))
  299. try
  300. {
  301. IsCustomLayout = true;
  302. Content = null;
  303. Details = XamlReader.Parse(xaml) as DynamicTabControl;
  304. Content = Details;
  305. Details.ApplyTemplate();
  306. var iHeight = Details.Height > 0 ? Details.Height : 600;
  307. var iWidth = Details.Width > 0 ? Details.Width : 800;
  308. Details.Height = double.NaN;
  309. Details.Width = double.NaN;
  310. OnEditorCreated?.Invoke(this, iHeight, iWidth);
  311. return true;
  312. }
  313. catch (Exception e)
  314. {
  315. MessageBox.Show(string.Format("Unable to Load XAML!\n\n{0}", e.Message));
  316. }
  317. return false;
  318. }
  319. private decimal GetSequence(DynamicGridColumn column)
  320. {
  321. if (OnGetSequence != null)
  322. return OnGetSequence.Invoke(column);
  323. return 999;
  324. }
  325. private void CreateLayout()
  326. {
  327. //Stopwatch sw = new Stopwatch();
  328. //sw.Start();
  329. IsCustomLayout = false;
  330. Content = null;
  331. Details = new DynamicTabControl();
  332. Details.VerticalAlignment = VerticalAlignment.Stretch;
  333. Details.HorizontalAlignment = HorizontalAlignment.Stretch;
  334. Details.Name = "Details";
  335. //Logger.Send(LogType.Information, "DEG.CreateLayout", String.Format("Created Tab Control: {0}", sw.ElapsedMilliseconds));
  336. //sw.Restart();
  337. var EditorGrids = new Dictionary<string, Grid>();
  338. CustomGrid = EnsureGrid(EditorGrids, "Custom Fields");
  339. EditorGrid = EnsureGrid(EditorGrids, "General");
  340. //Logger.Send(LogType.Information, "DEG.CreateLayout", String.Format("Ensured Grids: {0}", sw.ElapsedMilliseconds));
  341. //sw.Restart();
  342. Details.SelectionChanged += Details_SelectionChanged;
  343. Content = Details;
  344. editors.Clear();
  345. double fGeneralHeight = 30; // Allow for Tab Header
  346. //Logger.Send(LogType.Information, "DEG.CreateLayout", String.Format("Sorted Columns: {0}", sw.ElapsedMilliseconds));
  347. //sw.Restart();
  348. long total = 0;
  349. foreach (var column in _columns.OrderBy(x => GetSequence(x)))
  350. {
  351. var iProp = DatabaseSchema.Property(UnderlyingType, column.ColumnName);
  352. var editor = OnGetEditor?.Invoke(column);
  353. if (editor != null && iProp?.ShouldShowEditor() != true)
  354. {
  355. editor.Visible = Visible.Hidden;
  356. editor.Editable = Editable.Hidden;
  357. }
  358. OnGridCustomiseEditor?.Invoke(this, column, editor);
  359. if (editor != null && editor.Editable != Editable.Hidden)
  360. {
  361. var page = string.IsNullOrWhiteSpace(editor.Page) ? iProp is StandardProperty ? "General" : "Custom Fields" : editor.Page;
  362. var grid = EnsureGrid(EditorGrids, page);
  363. //List<Object> parameters = editor.Parameters != null ? editor.Parameters.ToList() : new List<object>();
  364. //bool bParams = true;
  365. BaseDynamicEditorControl? element = null;
  366. switch (editor)
  367. {
  368. case TextBoxEditor:
  369. element = new TextBoxEditorControl();
  370. break;
  371. case Core.RichTextEditor:
  372. element = new RichTextEditorControl();
  373. break;
  374. case URLEditor:
  375. element = new URLEditorControl();
  376. break;
  377. case CodeEditor:
  378. case UniqueCodeEditor:
  379. element = new CodeEditorControl();
  380. break;
  381. case CheckBoxEditor:
  382. element = new CheckBoxEditorControl();
  383. break;
  384. case DateTimeEditor:
  385. element = new DateTimeEditorControl();
  386. break;
  387. case DateEditor:
  388. element = new DateEditorControl { TodayVisible = (editor as DateEditor).TodayVisible };
  389. break;
  390. case TimeOfDayEditor:
  391. element = new TimeOfDayEditorControl { NowButtonVisible = false };
  392. break;
  393. case DurationEditor:
  394. element = new DurationEditorControl();
  395. break;
  396. case NotesEditor:
  397. element = new NotesEditorControl();
  398. break;
  399. case PINEditor:
  400. element = new PINEditorControl();
  401. break;
  402. case CheckListEditor:
  403. element = new CheckListBoxEditorControl();
  404. break;
  405. case MemoEditor:
  406. element = new MemoEditorControl();
  407. break;
  408. case JsonEditor:
  409. element = new JsonEditorControl();
  410. break;
  411. case LookupEditor:
  412. element = ClientFactory.IsSupported(((LookupEditor)editor).Type) ? new LookupEditorControl() : null;
  413. break;
  414. case PopupEditor:
  415. element = ClientFactory.IsSupported(((PopupEditor)editor).Type) ? new PopupEditorControl() : null;
  416. break;
  417. case CodePopupEditor:
  418. element = ClientFactory.IsSupported(((CodePopupEditor)editor).Type) ? new CodePopupEditorControl() : null;
  419. break;
  420. case EnumLookupEditor:
  421. case ComboLookupEditor:
  422. element = new LookupEditorControl();
  423. break;
  424. case EmbeddedImageEditor:
  425. element = new EmbeddedImageEditorControl
  426. {
  427. MaximumHeight = (editor as EmbeddedImageEditor).MaximumHeight,
  428. MaximumWidth = (editor as EmbeddedImageEditor).MaximumWidth,
  429. MaximumFileSize = (editor as EmbeddedImageEditor).MaximumFileSize
  430. };
  431. break;
  432. case FileNameEditor:
  433. element = new FileNameEditorControl
  434. {
  435. Filter = (editor as FileNameEditor).FileMask,
  436. AllowView = (editor as FileNameEditor).AllowView,
  437. RequireExisting = (editor as FileNameEditor).RequireExisting
  438. };
  439. break;
  440. case FolderEditor:
  441. element = new FolderEditorControl
  442. {
  443. InitialFolder = (editor as FolderEditor).InitialFolder
  444. };
  445. break;
  446. case MiscellaneousDocumentEditor:
  447. element = new DocumentEditorControl();
  448. break;
  449. case ImageDocumentEditor:
  450. element = new DocumentEditorControl();
  451. break;
  452. case VectorDocumentEditor:
  453. element = new DocumentEditorControl();
  454. break;
  455. case PDFDocumentEditor:
  456. element = new DocumentEditorControl();
  457. break;
  458. case PasswordEditor:
  459. element = new PasswordEditorControl();
  460. break;
  461. case CurrencyEditor:
  462. element = new CurrencyEditorControl();
  463. break;
  464. case DoubleEditor:
  465. element = new DoubleEditorControl();
  466. break;
  467. case IntegerEditor:
  468. element = new IntegerEditorControl();
  469. break;
  470. case Core.ScriptEditor:
  471. element = new ScriptEditorControl
  472. {
  473. SyntaxLanguage = (editor as Core.ScriptEditor).SyntaxLanguage
  474. };
  475. break;
  476. case TimestampEditor:
  477. element = new TimestampEditorControl();
  478. break;
  479. case ColorEditor:
  480. element = new ColorEditorControl();
  481. break;
  482. case FilterEditor filter:
  483. element = new FilterEditorControl { FilterType = filter.Type! };
  484. break;
  485. case ExpressionEditor expression:
  486. element = new ExpressionEditorControl();
  487. break;
  488. default:
  489. element = null;
  490. break;
  491. }
  492. if (element != null)
  493. {
  494. element.EditorDefinition = editor; //22
  495. element.IsEnabled = editor.Editable == Editable.Enabled;
  496. if (!string.IsNullOrWhiteSpace(editor.ToolTip))
  497. {
  498. element.ToolTip = new ToolTip() { Content = editor.ToolTip };
  499. }
  500. var label = new Label();
  501. label.Content = CoreUtils.Neatify(editor.Caption); // 2
  502. label.Margin = new Thickness(0F, 0F, 0F, 0F);
  503. label.HorizontalAlignment = HorizontalAlignment.Stretch;
  504. label.VerticalAlignment = VerticalAlignment.Stretch;
  505. label.HorizontalContentAlignment = HorizontalAlignment.Left;
  506. label.VerticalContentAlignment = VerticalAlignment.Center;
  507. label.SetValue(Grid.RowProperty, grid.RowDefinitions.Count);
  508. label.SetValue(Grid.ColumnProperty, 0);
  509. label.Visibility = string.IsNullOrWhiteSpace(editor.Caption) ? Visibility.Collapsed : Visibility.Visible;
  510. grid.Children.Add(label);
  511. element.ColumnName = column.ColumnName;
  512. element.Color = editor is UniqueCodeEditor ? Color.FromArgb(0xFF, 0xF6, 0xC9, 0xE8) : Colors.LightYellow;
  513. editors.Add(element);
  514. element.Margin = new Thickness(5F, 2.5F, 5F, 2.5F);
  515. double iHeight = element.DesiredHeight();
  516. if (iHeight == int.MaxValue)
  517. {
  518. grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
  519. fGeneralHeight += grid == EditorGrid ? element.MinHeight + 5.0F : 0.0F;
  520. }
  521. else
  522. {
  523. grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(iHeight + 5.0F) });
  524. fGeneralHeight += grid == EditorGrid ? iHeight + 5.0F : 0.0F;
  525. }
  526. double iWidth = element.DesiredWidth();
  527. if (iWidth == int.MaxValue)
  528. {
  529. element.HorizontalAlignment = HorizontalAlignment.Stretch;
  530. }
  531. else
  532. {
  533. element.HorizontalAlignment = HorizontalAlignment.Left;
  534. element.Width = iWidth;
  535. }
  536. element.SetValue(Grid.RowProperty, grid.RowDefinitions.Count - 1);
  537. element.SetValue(Grid.ColumnProperty, 1);
  538. grid.Children.Add(element);
  539. }
  540. }
  541. }
  542. //Logger.Send(LogType.Information, "DEG.CreateLayout", String.Format("Created Editors: {0}", sw.ElapsedMilliseconds));
  543. //sw.Restart();
  544. OnEditorCreated?.Invoke(this, fGeneralHeight, 800);
  545. var custom = Details.Items[Details.Items.Count - 1] as DynamicTabItem;
  546. custom.Visibility = CustomGrid.Children.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
  547. //Logger.Send(LogType.Information, "DEG.CreateLayout", String.Format("Finalised: {0}", sw.ElapsedMilliseconds));
  548. //sw.Stop();
  549. }
  550. private Grid EnsureGrid(Dictionary<string, Grid> grids, string caption)
  551. {
  552. if (grids.ContainsKey(caption))
  553. return grids[caption];
  554. // Create Editor, ScrollViewer and TabItem for Dynamic Editor
  555. var result = new Grid
  556. {
  557. HorizontalAlignment = HorizontalAlignment.Stretch,
  558. VerticalAlignment = VerticalAlignment.Stretch,
  559. //Background = new SolidColorBrush(Colors.Blue),
  560. Margin = new Thickness(0, 2.5, 0, 2.5)
  561. };
  562. result.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
  563. result.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  564. var scroll = new ScrollViewer
  565. {
  566. HorizontalAlignment = HorizontalAlignment.Stretch,
  567. VerticalAlignment = VerticalAlignment.Stretch,
  568. VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
  569. Padding = new Thickness(2)
  570. };
  571. scroll.Content = result;
  572. var border = new Border
  573. {
  574. BorderBrush = new SolidColorBrush(Colors.Gray),
  575. Background = new SolidColorBrush(Colors.White),
  576. BorderThickness = new Thickness(0.75)
  577. };
  578. border.Child = scroll;
  579. var tab = new DynamicTabItem();
  580. tab.Header = caption;
  581. tab.Content = border;
  582. if (Details.Items.Count == 0)
  583. Details.Items.Add(tab);
  584. else
  585. Details.Items.Insert(Details.Items.Count - 1, tab);
  586. grids[caption] = result;
  587. return result;
  588. }
  589. //List<TabItem> configuredpages = new List<TabItem>();
  590. private void Details_SelectionChanged(object sender, SelectionChangedEventArgs e)
  591. {
  592. if (bChanging || Details?.SelectedItem == null || e.OriginalSource != Details)
  593. return;
  594. bChanging = true;
  595. try
  596. {
  597. var tab = Details.SelectedItem as DynamicTabItem;
  598. var page = tab.Content as IDynamicEditorPage;
  599. if (page != null)
  600. {
  601. if (!page.Ready)
  602. using (new WaitCursor())
  603. {
  604. OnLoadPage?.Invoke(page);
  605. }
  606. }
  607. else
  608. {
  609. if (!_loaded || e.RemovedItems.Count == 0 || e.AddedItems.Count == 0 || e.AddedItems?[0] == e.RemovedItems?[0])
  610. return;
  611. //if (!configuredpages.Contains(tab))
  612. //{
  613. // ConfigureEditors(eds);
  614. // configuredpages.Add(tab);
  615. //}
  616. var eds = editors
  617. .Where(x => x is BaseDynamicEditorControl &&
  618. (x as FrameworkElement).Parent == ((tab.Content as Border).Child as ScrollViewer).Content)
  619. .Select(x => (BaseDynamicEditorControl)x);
  620. foreach (var ed in eds)
  621. {
  622. var editorvalue = ed.GetValue();
  623. var entityvalue = OnGetPropertyValue?.Invoke(this, ed.ColumnName);
  624. if (!Equals(editorvalue, entityvalue))
  625. {
  626. ed.Loaded = false;
  627. ed.SetValue(entityvalue);
  628. ed.Loaded = true;
  629. }
  630. }
  631. }
  632. OnSelectPage?.Invoke(tab, null);
  633. }
  634. finally
  635. {
  636. bChanging = false;
  637. }
  638. }
  639. public void UnloadPages(bool saved)
  640. {
  641. foreach (var page in Pages)
  642. if (page.Ready)
  643. OnUnloadPage?.Invoke(page, saved);
  644. }
  645. private void Lookup_OnUpdateOtherEditor(string columnname, object value)
  646. {
  647. var editor = editors.FirstOrDefault(x => x.ColumnName.Equals(columnname));
  648. if (editor != null)
  649. CoreUtils.SetPropertyValue(editor, "Value", value);
  650. }
  651. private string FormatXML(string xml)
  652. {
  653. var result = "";
  654. var mStream = new MemoryStream();
  655. var writer = new XmlTextWriter(mStream, Encoding.Unicode);
  656. var document = new XmlDocument();
  657. try
  658. {
  659. // Load the XmlDocument with the XML.
  660. document.LoadXml(xml);
  661. writer.Formatting = Formatting.Indented;
  662. // Write the XML into a formatting XmlTextWriter
  663. document.WriteContentTo(writer);
  664. writer.Flush();
  665. mStream.Flush();
  666. // Have to rewind the MemoryStream in order to read
  667. // its contents.
  668. mStream.Position = 0;
  669. // Read MemoryStream contents into a StreamReader.
  670. var sReader = new StreamReader(mStream);
  671. // Extract the text from the StreamReader.
  672. var formattedXml = sReader.ReadToEnd();
  673. result = formattedXml;
  674. }
  675. catch (XmlException)
  676. {
  677. // Handle the exception
  678. }
  679. mStream.Close();
  680. writer.Close();
  681. return result;
  682. }
  683. public void EditLayout()
  684. {
  685. ClearPages();
  686. //UnloadEditorValues();
  687. var xaml = new GlobalConfiguration<ScreenLayout>(_layoutname).Load().XAML;
  688. if (string.IsNullOrWhiteSpace(xaml))
  689. {
  690. Details.Height = Details.ActualHeight;
  691. Details.Width = Details.ActualWidth;
  692. //xaml = XamlWriter.Save(GetParentWindow(Details));
  693. xaml = XamlWriter.Save(Details);
  694. }
  695. xaml = FormatXML(xaml);
  696. var scripteditor = new ScriptEditor(xaml, SyntaxLanguage.XAML);
  697. if (scripteditor.ShowDialog() == true)
  698. {
  699. var layout = new ScreenLayout { XAML = scripteditor.Script };
  700. new GlobalConfiguration<ScreenLayout>(_layoutname).Save(layout);
  701. Content = null;
  702. if (!LoadLayout(layout.XAML))
  703. if (!LoadLayout(xaml))
  704. CreateLayout();
  705. Details.ApplyTemplate();
  706. Application.Current.Dispatcher.Invoke(() =>
  707. {
  708. ConfigureEditors();
  709. LoadEditorValues();
  710. AddPages();
  711. DoReconfigureEditors();
  712. }, DispatcherPriority.Render);
  713. }
  714. }
  715. internal void ResetLayout()
  716. {
  717. new GlobalConfiguration<ScreenLayout>(_layoutname).Delete();
  718. ClearPages();
  719. //UnloadEditorValues();
  720. CreateLayout();
  721. LoadEditorValues();
  722. AddPages();
  723. DoReconfigureEditors();
  724. }
  725. private void LoadEditor(string columnname, object value)
  726. {
  727. }
  728. private void EditorValueChanged(IDynamicEditorControl sender, Dictionary<string, object> values)
  729. {
  730. //Logger.Send(LogType.Information, "", string.Format("DynamicEditorGrid.EditorValueChanged({0})", values.Keys.Count));
  731. var changededitors = new Dictionary<string, object>();
  732. foreach (var key in values.Keys)
  733. {
  734. var changedcolumns = OnEditorValueChanged?.Invoke(this, key, values[key]);
  735. if (changedcolumns != null)
  736. foreach (var change in changedcolumns.Keys)
  737. if (editors.Any(x => x.ColumnName.Equals(change)) && !changededitors.ContainsKey(change) && !change.Equals(sender.ColumnName))
  738. changededitors[change] = changedcolumns[change];
  739. }
  740. if (changededitors.Any())
  741. LoadEditorValues(changededitors);
  742. DoReconfigureEditors();
  743. }
  744. private void LoadEditorValues(Dictionary<string, object> changededitors = null)
  745. {
  746. var columnnames = changededitors != null ? changededitors.Keys.ToArray() : editors.Select(x => x.ColumnName).ToArray();
  747. foreach (var columnname in columnnames)
  748. {
  749. var editor = editors.FirstOrDefault(x => x.ColumnName.Equals(columnname));
  750. if (editor == null)
  751. continue;
  752. var bLoaded = editor.Loaded;
  753. editor.Loaded = false;
  754. if (changededitors != null && changededitors.ContainsKey(columnname))
  755. {
  756. CoreUtils.SetPropertyValue(editor, "Value", changededitors[columnname]);
  757. }
  758. else
  759. {
  760. var curvalue = OnGetPropertyValue?.Invoke(this, columnname);
  761. try
  762. {
  763. CoreUtils.SetPropertyValue(editor, "Value", curvalue);
  764. }
  765. catch (Exception e)
  766. {
  767. MessageBox.Show(string.Format("Unable to set editor value for {0} -> {1}", columnname, curvalue));
  768. }
  769. CoreUtils.SetPropertyValue(editor, "Changed", false);
  770. }
  771. editor.Loaded = bLoaded;
  772. editor.OnEditorValueChanged += EditorValueChanged;
  773. }
  774. }
  775. public virtual void DoReconfigureEditors()
  776. {
  777. ReconfigureEditors?.Invoke(this);
  778. }
  779. public void Load(string layoutname, DynamicEditorPages pages = null)
  780. {
  781. _layoutname = layoutname;
  782. Pages = pages;
  783. //Stopwatch sw = new Stopwatch();
  784. //sw.Start();
  785. _columns = OnCustomiseColumns?.Invoke(this, null);
  786. //Logger.Send(LogType.Information, "DEG.Load", String.Format("Loaded Columns: {0}", sw.ElapsedMilliseconds));
  787. //sw.Restart();
  788. var layout = new GlobalConfiguration<ScreenLayout>(_layoutname).Load();
  789. //Logger.Send(LogType.Information, "DEG.Load", String.Format("Loaded Layout: {0}", sw.ElapsedMilliseconds));
  790. //sw.Restart();
  791. if (!LoadLayout(layout.XAML))
  792. CreateLayout();
  793. //Logger.Send(LogType.Information, "DEG.Load", String.Format("Created Layout: {0}", sw.ElapsedMilliseconds));
  794. //sw.Restart();
  795. }
  796. protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
  797. {
  798. base.OnRenderSizeChanged(sizeInfo);
  799. foreach (var columnname in editors.Select(x => x.ColumnName).ToArray())
  800. {
  801. var editor = editors.FirstOrDefault(x => x.ColumnName.Equals(columnname));
  802. editor.Loaded = true;
  803. }
  804. }
  805. public bool Unload()
  806. {
  807. ClearPages();
  808. var bChanged = false;
  809. foreach (var columnname in changes.Keys)
  810. {
  811. OnSetPropertyValue?.Invoke(this, columnname, changes[columnname]);
  812. bChanged = true;
  813. }
  814. return bChanged;
  815. }
  816. private void AddPages()
  817. {
  818. if (Pages != null)
  819. using (new WaitCursor())
  820. {
  821. foreach (var page in Pages.OrderBy(x => x.Order()).ThenBy(x => x.Caption()))
  822. {
  823. var tab = new DynamicTabItem();
  824. tab.Header = page.Caption();
  825. tab.Content = page;
  826. Details.Items.Insert(Details.Items.Count - 1, tab);
  827. pagemap[page] = tab;
  828. if (PreloadPages)
  829. OnLoadPage?.Invoke(page);
  830. page.EditorGrid = this;
  831. }
  832. }
  833. //if (Details.Items.Count <= 2)
  834. // ((TabItem)Details.Items[0]).Visibility = Visibility.Collapsed;
  835. }
  836. private void ClearPages()
  837. {
  838. foreach (var page in pagemap.Keys)
  839. {
  840. var tab = pagemap[page];
  841. tab.Content = null;
  842. Details.Items.Remove(tab);
  843. }
  844. pagemap.Clear();
  845. //if (_pages != null)
  846. //{
  847. // foreach (var page in _pages)
  848. // {
  849. // var tab = Details.Items.OfType<TabItem>().FirstOrDefault(x => x.Content.Equals(page));
  850. // if (tab != null)
  851. // {
  852. // tab.Content = null;
  853. // Details.Items.Remove(tab);
  854. // }
  855. // }
  856. //}
  857. }
  858. }
  859. }