QAFormViewer.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using System.Linq;
  5. using Xamarin.Forms;
  6. using InABox.Core;
  7. using InABox.Clients;
  8. using System.IO;
  9. using InABox.Mobile;
  10. using Comal.Classes;
  11. using PRSClasses;
  12. namespace PRS.Mobile
  13. {
  14. public class QAFormViewer : Grid, IDFRenderer
  15. {
  16. #region Fields
  17. // This connects the DFLayout elements to the respective UI elements
  18. public readonly Dictionary<DFLayoutField, IDigitalFormField> Bindings = new();
  19. // These get saved into FormData
  20. public DFLoadStorage Storage { get; private set; }
  21. // These are used to pre-populate the next instance of this form
  22. public DFLoadStorage RetainedData { get; private set; }
  23. //public readonly Dictionary<DFLayoutLookupField, Dictionary<Guid, string>> dfLayoutLookupFieldLookupOptions = new();
  24. private DFLayout _layout = new();
  25. private IDigitalFormDataModel? _model;
  26. const string nullOrInvalidType = "Null or Invalid Type";
  27. private readonly List<string> useSavedSignatures = new();
  28. public readonly List<string> errors = new();
  29. public bool isRequiredEmpty { get; set; }
  30. public string isRequiredMessage { get; set; } = "";
  31. private readonly Location location = new();
  32. private readonly Color isRequiredColor = Color.DarkOrange;
  33. private readonly Color isRequiredFrame = Color.Firebrick;
  34. private DateTime timeStarted = DateTime.MinValue;
  35. readonly List<DigitalFormHeader> headersToCollapse = new();
  36. #endregion
  37. #region Constructor
  38. public QAFormViewer()
  39. {
  40. Storage = new DFLoadStorage();
  41. RetainedData = new DFLoadStorage();
  42. }
  43. public QAFormViewer(IDigitalFormDataModel model, DFLayout layout,
  44. Guid job = default) : this()
  45. {
  46. Load(model, layout, job);
  47. }
  48. public void Load(IDigitalFormDataModel model, DFLayout layout, Guid job = default)
  49. {
  50. GetLocation();
  51. timeStarted = DateTime.Now;
  52. _model = model;
  53. _layout = layout;
  54. _layout.Renderer = this;
  55. isRequiredEmpty = false;
  56. isRequiredMessage = "";
  57. LoadFormLayout();
  58. Storage = DigitalForm.DeserializeFormData(_model.Instance) ?? new DFLoadStorage();
  59. LoadData();
  60. }
  61. #endregion
  62. #region Location
  63. private async void GetLocation()
  64. {
  65. await Task.Run(() =>
  66. {
  67. LocationServices locationServices = new LocationServices();
  68. locationServices.OnLocationFound += LocationFound;
  69. locationServices.OnLocationError += LocationError;
  70. locationServices.GetLocation();
  71. });
  72. }
  73. private void LocationFound(LocationServices sender)
  74. {
  75. location.Latitude = sender.Latitude;
  76. location.Longitude = sender.Longitude;
  77. }
  78. private void LocationError(LocationServices sender, Exception error)
  79. {
  80. errors.Add("Location error: " + error.Message);
  81. }
  82. #endregion Location
  83. #region Load and Save Data
  84. public void DuplicateInstance()
  85. {
  86. _model.DuplicateInstance();
  87. }
  88. public void LoadData()
  89. {
  90. foreach (DFLayoutField field in Bindings.Keys)
  91. {
  92. try
  93. {
  94. if (RetainedData.HasValue(field.Name))
  95. Bindings[field].Deserialize(RetainedData.GetEntry(field.Name));
  96. else //if (Storage.HasValue(field.Name))
  97. Bindings[field].Deserialize(Storage.GetEntry(field.Name));
  98. _layout.ChangeField(field.Name);
  99. }
  100. catch (Exception ex)
  101. {
  102. InABox.Mobile.MobileLogging.Log(ex,$"LoadData({field.Name})");
  103. }
  104. }
  105. }
  106. public void SaveData(bool saveForLater, bool deleteform)
  107. {
  108. try
  109. {
  110. var save = new DFSaveStorage();
  111. var retained = new DFSaveStorage();
  112. foreach (DFLayoutField field in Bindings.Keys)
  113. {
  114. var entry = save.GetEntry(field.Name);
  115. Bindings[field].Serialize(entry);
  116. if (field.GetProperties().Retain)
  117. {
  118. var retentry = retained.GetEntry(field.Name);
  119. Bindings[field].Serialize(retentry);
  120. }
  121. }
  122. UpdateModel(save, saveForLater, deleteform);
  123. Storage.Clear();
  124. RetainedData.Load(retained.FormData, retained.BlobData);
  125. }
  126. catch (Exception ex)
  127. {
  128. InABox.Mobile.MobileLogging.Log(ex,"SaveData");
  129. }
  130. }
  131. #endregion
  132. #region Load Form Layout
  133. private void LoadFormLayout()
  134. {
  135. RowDefinitions.Clear();
  136. foreach (var row in _layout.RowHeights)
  137. {
  138. RowDefinition def = new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) };
  139. SetRowHeight(row, def);
  140. RowDefinitions.Add(def);
  141. }
  142. ColumnDefinitions.Clear();
  143. foreach (var col in _layout.ColumnWidths)
  144. {
  145. ColumnDefinition def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) };
  146. def = SetColumnWidth(col, def);
  147. ColumnDefinitions.Add(def);
  148. }
  149. Children.Clear();
  150. foreach (DFLayoutControl element in _layout.Elements)
  151. LoadViewAccordingToElement(element);
  152. foreach (var header in headersToCollapse)
  153. AdjustHeaderSection(header, false);
  154. }
  155. private static void SetRowHeight(string row, RowDefinition def)
  156. {
  157. if (int.TryParse(row, out int rowHeight))
  158. def.Height = new GridLength(Math.Max(60, rowHeight), GridUnitType.Absolute);
  159. else if (row.Contains("*"))
  160. {
  161. def.Height = int.TryParse(row.Substring(0, row.IndexOf("*")), out int result)
  162. ? new GridLength(result, GridUnitType.Star)
  163. : new GridLength(1, GridUnitType.Star);
  164. }
  165. else
  166. def.Height = new GridLength(1, GridUnitType.Auto);
  167. }
  168. private static ColumnDefinition SetColumnWidth(string col, ColumnDefinition def)
  169. {
  170. if (int.TryParse(col, out int colWidth))
  171. def = new ColumnDefinition { Width = new GridLength(colWidth, GridUnitType.Absolute) };
  172. else if (col.Contains("*"))
  173. {
  174. def = int.TryParse(col.Substring(0, col.IndexOf("*")), out int result)
  175. ? new ColumnDefinition { Width = new GridLength(result, GridUnitType.Star) }
  176. : new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
  177. }
  178. return def;
  179. }
  180. private void LoadViewAccordingToElement(DFLayoutControl element)
  181. {
  182. // Not sure why this is here - perhaps to ry and handle malformed element definitions?
  183. if (string.IsNullOrEmpty(element.Description))
  184. return;
  185. if (element is DFLayoutLabel l)
  186. {
  187. var result = new DigitalFormLabel() { Definition = l };
  188. AddViewToGrid(result, element);
  189. }
  190. else if (element is DFLayoutImage img )
  191. {
  192. var result = new DigitalFormImage() { Definition = img };
  193. AddViewToGrid(result, element);
  194. }
  195. else if (element is DFLayoutHeader hdr)
  196. {
  197. var result = new DigitalFormHeader() { Definition = hdr };
  198. result.CollapsedChanged += (sender, args) => AdjustHeaderSection(result, result.Collapsed);
  199. if (hdr.Collapsed)
  200. headersToCollapse.Add(result);
  201. AddViewToGrid(result, element);
  202. }
  203. else if (element is DFLayoutBooleanField b)
  204. CreateView<DigitalFormBoolean, DFLayoutBooleanField, DFLayoutBooleanFieldProperties, bool, bool?>(b);
  205. else if (element is DFLayoutStringField s)
  206. {
  207. if (s.Properties.PopupEditor)
  208. CreateView<DigitalFormStringPopup, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  209. else if (s.Properties.TextWrapping)
  210. CreateView<DigitalFormStringEditor, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  211. else
  212. CreateView<DigitalFormStringEntry, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  213. }
  214. else if (element is DFLayoutIntegerField i)
  215. CreateView<DigitalFormIntegerEntry, DFLayoutIntegerField, DFLayoutIntegerFieldProperties, int, int?>(i);
  216. else if (element is DFLayoutDoubleField d)
  217. CreateView<DigitalFormDoubleEntry, DFLayoutDoubleField, DFLayoutDoubleFieldProperties, double, double?>(d);
  218. else if (element is DFLayoutDateField df)
  219. CreateView<DigitalFormDateEntry, DFLayoutDateField, DFLayoutDateFieldProperties, DateTime, DateTime?>(df);
  220. else if (element is DFLayoutTimeField tf)
  221. CreateView<DigitalFormTimeEntry, DFLayoutTimeField, DFLayoutTimeFieldProperties, TimeSpan,TimeSpan?>(tf);
  222. else if (element is DFLayoutOptionField of)
  223. {
  224. if (of.Properties.OptionType == DFLayoutOptionType.Radio)
  225. CreateView<DigitalFormOptionRadioList, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  226. else if (of.Properties.OptionType == DFLayoutOptionType.Buttons)
  227. CreateView<DigitalFormOptionButtonList, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  228. else
  229. CreateView<DigitalFormOptionComboBox, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  230. }
  231. else if (element is DFLayoutLookupField lf)
  232. {
  233. if (lf.Properties.DisplayType == DFLayoutLookupDisplayType.Combo)
  234. CreateView<DigitalFormLookupComboBox, DFLayoutLookupField, DFLayoutLookupFieldProperties, Guid, DFLayoutLookupValue>(lf);
  235. else
  236. CreateView<DigitalFormLookupButton, DFLayoutLookupField, DFLayoutLookupFieldProperties, Guid, DFLayoutLookupValue>(lf);
  237. }
  238. else if (element is DFLayoutSignaturePad sp)
  239. CreateView<DigitalFormSignature, DFLayoutSignaturePad, DFLayoutSignaturePadProperties, byte[], byte[]?>(sp);
  240. else if (element is DFLayoutEmbeddedImage ei)
  241. CreateView<DigitalFormEmbeddedImage, DFLayoutEmbeddedImage, DFLayoutEmbeddedImageProperties, Guid, DFLayoutEmbeddedMediaValue>(ei);
  242. else if (element is DFLayoutVideoField ev)
  243. CreateView<DigitalFormEmbeddedVideo, DFLayoutVideoField, DFLayoutVideoFieldProperties, byte[], DFLayoutEmbeddedMediaValue>(ev);
  244. else if (element is DFLayoutMultiImage mi)
  245. CreateView<DigitalFormMultiImage, DFLayoutMultiImage, DFLayoutMultiImageProperties, List<Guid>, DFLayoutEmbeddedMediaValues>(mi);
  246. else if (element is DFLayoutMultiSignaturePad ms)
  247. {
  248. CreateView<DigitalFormMultiSignature, DFLayoutMultiSignaturePad, DFLayoutMultiSignaturePadProperties,
  249. Dictionary<string, byte[]>, Dictionary<string, byte[]>?>(ms);
  250. //var tuple = LoadMultiSignaturePad(element);
  251. //AddViewToGrid(tuple.Item1, element);
  252. }
  253. else if (element is DFLayoutAddTaskField at)
  254. {
  255. CreateView<DigitalFormAddTask, DFLayoutAddTaskField, DFLayoutAddTaskFieldProperties,
  256. string?, string?>(at);
  257. //var tuple = LoadAddTaskField(element);
  258. //AddViewToGrid(tuple.Item1, element);
  259. }
  260. }
  261. private TField CreateView<TField, TDefinition, TProperties, TValue, TSerialized>(TDefinition definition)
  262. where TField : View, IDigitalFormField<TDefinition, TProperties, TValue, TSerialized>, new()
  263. where TDefinition : DFLayoutField<TProperties>
  264. where TProperties : DFLayoutFieldProperties<TValue, TSerialized>, new()
  265. {
  266. TField item = new TField()
  267. {
  268. Definition = definition,
  269. IsEnabled = !definition.GetProperties().Secure
  270. && _model.Instance.FormCompleted.IsEmpty()
  271. && string.IsNullOrWhiteSpace(definition.GetPropertyValue<string>("Expression")),
  272. };
  273. item.ValueChanged += (sender, args) =>
  274. {
  275. // Update Object?
  276. var property = args.Definition.GetProperties().Property;
  277. if (!String.IsNullOrWhiteSpace(property))
  278. CoreUtils.SetPropertyValue(_model.Entity,property,args.Value);
  279. foreach (var other in Bindings.Keys.Where(x=>x.Name != args.Definition.Name))
  280. {
  281. var linked = other.GetProperties().Property;
  282. if (!String.IsNullOrWhiteSpace(linked))
  283. {
  284. try
  285. {
  286. var linkedvalue = CoreUtils.GetPropertyValue(_model.Entity, linked);
  287. // Problem - linkedvalue might not be the same as the
  288. //CoreUtils.SetPropertyValue(pairs[other],"Value",linkedvalue);
  289. }
  290. catch (Exception e)
  291. {
  292. MobileLogging.Log(e,"QAFormViewer:Item.ValueChanged()");
  293. }
  294. }
  295. }
  296. // Update ChangedLinkedProperties?
  297. // Run Expressions and Scripts?
  298. // Update Dictionary?
  299. };
  300. Bindings[definition] = item;
  301. AddViewToGrid(item, definition);
  302. return item;
  303. }
  304. private void AddViewToGrid(View view, DFLayoutControl element)
  305. {
  306. //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)
  307. SetRow(view, Math.Max(0,element.Row - 1));
  308. SetRowSpan(view, Math.Max(1,element.RowSpan));
  309. SetColumn(view, Math.Max(0,element.Column - 1));
  310. SetColumnSpan(view, Math.Max(1,element.ColumnSpan));
  311. Children.Add(view);
  312. }
  313. private void AdjustHeaderSection(DigitalFormHeader header, bool collapsed)
  314. {
  315. try
  316. {
  317. var thisHeaderRow = GetRow(header);
  318. var headerRows = Children.OfType<DigitalFormHeader>().Select(x => GetRow(x)).OrderBy(x=>x).ToArray();
  319. if (headerRows.Any())
  320. AdjustHeightsToNextHeader(headerRows, thisHeaderRow, collapsed);
  321. else
  322. AdjustHeightsBelowHeader(headerRows, thisHeaderRow, collapsed);
  323. }
  324. catch (Exception ex)
  325. {
  326. MobileLogging.Log(ex, "AdjustHeaderSection()");
  327. }
  328. }
  329. private void AdjustHeightsToNextHeader(int[] headerRows, int thisHeaderRow, bool collapsed)
  330. {
  331. int nextHeaderRow = headerRows[0];
  332. for (int i = thisHeaderRow + 1; i < nextHeaderRow; i++)
  333. AdjustHeight(i, collapsed);
  334. }
  335. private void AdjustHeightsBelowHeader(int[] headerRows, int thisHeaderRow, bool collapsed)
  336. {
  337. for (int i = thisHeaderRow + 1; i < RowDefinitions.Count; i++)
  338. AdjustHeight(i, collapsed);
  339. }
  340. private void AdjustHeight(int i, bool collapsed)
  341. {
  342. var rowdef = RowDefinitions[i];
  343. if (collapsed)
  344. SetRowHeight(_layout.RowHeights[i], rowdef);
  345. else
  346. rowdef.Height = 0;
  347. }
  348. // private Tuple<View, bool> LoadMultiSignaturePad(DFLayoutControl element)
  349. // {
  350. // string value = "";
  351. // DFLayoutMultiSignaturePad dfLayoutMultiSignaturePad = element as DFLayoutMultiSignaturePad;
  352. // DataButtonControl button = new DataButtonControl
  353. // {
  354. // Text = "Add Signatures",
  355. // };
  356. // if (Storage.TryGetValue(dfLayoutMultiSignaturePad.Name, out value))
  357. // {
  358. // button.Data = value;
  359. // }
  360. // MultiSignaturePad multiSignaturePad = new MultiSignaturePad(button.Data);
  361. // multiSignaturePad.OnMultiSignatureSaved += (result) =>
  362. // {
  363. // button.Data = result;
  364. // };
  365. // button.Clicked += (object sender, MobileButtonClickEventArgs e) =>
  366. // {
  367. // Navigation.PushAsync(multiSignaturePad);
  368. // };
  369. //
  370. // if (dfLayoutMultiSignaturePad.Properties.Required)
  371. // {
  372. // button.BackgroundColor = isRequiredColor;
  373. // button.BorderColor = isRequiredFrame;
  374. // }
  375. // else if (!_model.Instance.FormCompleted.IsEmpty())
  376. // {
  377. // button.BackgroundColor = Color.Silver;
  378. // button.BorderColor = Color.Gray;
  379. // }
  380. //
  381. // return new Tuple<View, bool>(button, dfLayoutMultiSignaturePad.Properties.Required);
  382. // }
  383. // private Tuple<View, bool> LoadAddTaskField(DFLayoutControl element)
  384. // {
  385. // string value = "";
  386. // DFLayoutAddTaskField field = element as DFLayoutAddTaskField;
  387. // DFCreateTaskView taskView = new DFCreateTaskView();
  388. // taskView.OnAddTaskButtonClicked += () =>
  389. // {
  390. // AddEditTask addEditTask = new AddEditTask(Guid.Empty, "New task from Digital Form");
  391. // if (field.Properties.TaskType != null)
  392. // {
  393. // addEditTask.kanban.Type.ID = field.Properties.TaskType.ID;
  394. // try
  395. // {
  396. // addEditTask.kanban.Type.Description = new Client<KanbanType>().Query(
  397. // new Filter<KanbanType>(x => x.ID).IsEqualTo(field.Properties.TaskType.ID),
  398. // new Columns<KanbanType>(x => x.Description)
  399. // ).Rows.FirstOrDefault()?.Get<KanbanType,String>(c=>c.Description) ?? "";
  400. // }
  401. // catch (Exception ex)
  402. // {
  403. // MobileLogging.Log(ex,"LoadAddTaskField");
  404. // }
  405. // addEditTask.UpdateScreen(true);
  406. // }
  407. // addEditTask.OnTaskSaved += (taskNumber) =>
  408. // {
  409. // taskView.DisableButton();
  410. // taskView.TaskNumber = taskNumber.ToString();
  411. // };
  412. // Navigation.PushAsync(addEditTask);
  413. // };
  414. // if (Storage.TryGetValue(field.Name, out value))
  415. // {
  416. // taskView.TaskNumber = value;
  417. // taskView.DisableButton();
  418. // }
  419. //
  420. // return new Tuple<View, bool>(taskView, field.Properties.Required);
  421. // }
  422. #endregion
  423. #region Checks / Custom methods
  424. private void CheckRequired(DFLayoutField field)
  425. {
  426. if (field is DFLayoutStringField)
  427. {
  428. if ((field as DFLayoutStringField).Properties.Required)
  429. {
  430. isRequiredEmpty = true;
  431. isRequiredMessage = (field as DFLayoutStringField).Description;
  432. }
  433. }
  434. else if (field is DFLayoutIntegerField)
  435. {
  436. if ((field as DFLayoutIntegerField).Properties.Required)
  437. {
  438. isRequiredEmpty = true;
  439. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  440. }
  441. }
  442. else if (field is DFLayoutDoubleField)
  443. {
  444. if ((field as DFLayoutDoubleField).Properties.Required)
  445. {
  446. {
  447. isRequiredEmpty = true;
  448. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  449. }
  450. }
  451. }
  452. else if (field is DFLayoutBooleanField)
  453. {
  454. if ((field as DFLayoutBooleanField).Properties.Required)
  455. {
  456. {
  457. isRequiredEmpty = true;
  458. isRequiredMessage = (field as DFLayoutBooleanField).Description;
  459. }
  460. }
  461. }
  462. else if (field is DFLayoutDateField)
  463. {
  464. if ((field as DFLayoutDateField).Properties.Required)
  465. {
  466. {
  467. isRequiredEmpty = true;
  468. isRequiredMessage = (field as DFLayoutDateField).Description;
  469. }
  470. }
  471. }
  472. else if (field is DFLayoutTimeField)
  473. {
  474. if ((field as DFLayoutTimeField).Properties.Required)
  475. {
  476. {
  477. isRequiredEmpty = true;
  478. isRequiredMessage = (field as DFLayoutTimeField).Description;
  479. }
  480. }
  481. }
  482. else if (field is DFLayoutOptionField)
  483. {
  484. if ((field as DFLayoutOptionField).Properties.Required)
  485. {
  486. {
  487. isRequiredEmpty = true;
  488. isRequiredMessage = (field as DFLayoutOptionField).Description;
  489. }
  490. }
  491. }
  492. else if (field is DFLayoutLookupField)
  493. {
  494. if ((field as DFLayoutLookupField).Properties.Required)
  495. {
  496. {
  497. isRequiredEmpty = true;
  498. isRequiredMessage = (field as DFLayoutLookupField).Description;
  499. }
  500. }
  501. }
  502. else if (field is DFLayoutSignaturePad)
  503. {
  504. if ((field as DFLayoutSignaturePad).Properties.Required)
  505. {
  506. {
  507. isRequiredEmpty = true;
  508. isRequiredMessage = (field as DFLayoutSignaturePad).Description;
  509. }
  510. }
  511. }
  512. else if (field is DFLayoutEmbeddedImage)
  513. {
  514. if ((field as DFLayoutEmbeddedImage).Properties.Required)
  515. {
  516. {
  517. isRequiredEmpty = true;
  518. isRequiredMessage = (field as DFLayoutEmbeddedImage).Description;
  519. }
  520. }
  521. }
  522. else if (field is DFLayoutMultiImage)
  523. {
  524. if ((field as DFLayoutMultiImage).Properties.Required)
  525. {
  526. {
  527. isRequiredEmpty = true;
  528. isRequiredMessage = (field as DFLayoutMultiImage).Description;
  529. }
  530. }
  531. }
  532. else if (field is DFLayoutMultiSignaturePad)
  533. {
  534. if ((field as DFLayoutMultiSignaturePad).Properties.Required)
  535. {
  536. {
  537. isRequiredEmpty = true;
  538. isRequiredMessage = (field as DFLayoutMultiSignaturePad).Description;
  539. }
  540. }
  541. }
  542. }
  543. //
  544. // {
  545. // StreamImageSource streamImageSource = (StreamImageSource)source;
  546. // System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;
  547. // Task<Stream> task = streamImageSource.Stream(cancellationToken);
  548. // Stream stream = task.Result;
  549. // byte[] bytes = new byte[stream.Length];
  550. // stream.Read(bytes, 0, bytes.Length);
  551. // string s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
  552. // return s;
  553. // }
  554. //
  555. // private string FindIDForDesignLookupField(DataButtonControl button)
  556. // {
  557. // try
  558. // {
  559. // string userInputValue = button.Data;
  560. // string guidString = "";
  561. // if (userInputValue != nullOrInvalidType)
  562. // {
  563. // foreach (KeyValuePair<DFLayoutLookupField, Dictionary<Guid, string>> pair in dfLayoutLookupFieldLookupOptions)
  564. // {
  565. // foreach (KeyValuePair<Guid, string> innerPair in pair.Value)
  566. // {
  567. // if (innerPair.Value == userInputValue)
  568. // {
  569. // guidString = innerPair.Key.ToString();
  570. // }
  571. // }
  572. // }
  573. // }
  574. //
  575. // return guidString;
  576. // }
  577. // catch (Exception e)
  578. // {
  579. // MobileLogging.Log(e,"FindIDForDesignLookupField");
  580. // return "";
  581. // }
  582. // }
  583. #endregion
  584. #region Save Completion
  585. //point of determination for whether or not QA form gets completed or saved for later
  586. private void UpdateModel(DFSaveStorage save, bool saveForLater, bool deleteform)
  587. {
  588. if (save.Count() > 0 && _model != null)
  589. {
  590. // Blobs are uploaded in the background by DigitalFormDocumentHandler class,
  591. // so the blob breakup doesn't have to happen anymore :-)
  592. DigitalForm.SerializeFormData(_model.Instance, _model.Variables, save);
  593. if (_model.Instance.FormStarted == DateTime.MinValue)
  594. _model.Instance.FormStarted = timeStarted;
  595. _model.Instance.FormOpen += (DateTime.Now - timeStarted);
  596. if (!saveForLater)
  597. {
  598. _model.Instance.FormCompleted = DateTime.Now;
  599. _model.Instance.FormCompletedBy.ID = App.Data.Me.UserID;
  600. _model.Instance.Location.Longitude = location.Longitude;
  601. _model.Instance.Location.Latitude = location.Latitude;
  602. _model.Instance.Location.Timestamp = _model.Instance.FormCompleted;
  603. }
  604. if (deleteform)
  605. _model.Instance.FormCancelled = DateTime.Now;
  606. _model.Update(null);
  607. }
  608. }
  609. #endregion
  610. #region Expressions
  611. public object GetFieldValue(string name)
  612. {
  613. try
  614. {
  615. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, name));
  616. if (definition != null)
  617. return CoreUtils.GetPropertyValue(Bindings[definition],"Value");
  618. }
  619. catch (Exception e)
  620. {
  621. MobileLogging.Log(e,"SetFieldValue");
  622. }
  623. return null;
  624. }
  625. public void SetFieldValue(string name, object value)
  626. {
  627. try
  628. {
  629. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, name));
  630. if (definition != null)
  631. CoreUtils.SetPropertyValue(Bindings[definition],"Value",value);
  632. }
  633. catch (Exception e)
  634. {
  635. MobileLogging.Log(e,"SetFieldValue");
  636. }
  637. }
  638. public object GetFieldData(string fieldName, string dataField)
  639. {
  640. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, fieldName));
  641. if ((definition != null) && (Bindings[definition] is DigitalFormLookupView lookup))
  642. return lookup.OtherValue(dataField);
  643. return null;
  644. }
  645. public void SetFieldColour(string field, System.Drawing.Color? colour = null)
  646. {
  647. if (colour != null)
  648. {
  649. try
  650. {
  651. System.Drawing.Color color = (System.Drawing.Color)colour;
  652. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, field));
  653. if (definition != null)
  654. {
  655. Bindings[definition].BackgroundColor = Color.FromRgba(
  656. Convert.ToDouble(color.R),
  657. Convert.ToDouble(color.G),
  658. Convert.ToDouble(color.B),
  659. Convert.ToDouble(color.A)
  660. );
  661. }
  662. }
  663. catch (Exception e)
  664. {
  665. MobileLogging.Log(e,"SetFieldColor");
  666. }
  667. }
  668. }
  669. #endregion
  670. }
  671. }