Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ParameterDialog.xaml.cs
1using ICSharpCode.AvalonEdit.Highlighting;
2using ICSharpCode.AvalonEdit.Highlighting.Xshd;
3using System;
4using System.Collections.Generic;
5using System.IO;
6using System.Threading.Tasks;
7using System.Windows;
8using System.Windows.Controls;
9using System.Windows.Documents;
10using System.Windows.Media;
11using System.Windows.Media.Imaging;
12using System.Xml;
14using Waher.Content;
16using Waher.Events;
21
23{
27 public partial class ParameterDialog : Window
28 {
29 private readonly DataForm form;
30 private FrameworkElement makeVisible = null;
31 private bool empty = true;
32
33 private ParameterDialog(DataForm Form)
34 {
35 this.form = Form;
37 }
38
42 public bool Empty => this.empty;
43
47 public static async Task<ParameterDialog> CreateAsync(DataForm Form)
48 {
49 ParameterDialog Result = new ParameterDialog(Form)
50 {
51 Title = Form.Title
52 };
53
54 Panel Container = Result.DialogPanel;
55 TabControl TabControl = null;
56 TabItem TabItem;
57 StackPanel StackPanel;
58 ScrollViewer ScrollViewer;
59 Control First = null;
60 Control Control;
61
62 if (Form.HasPages)
63 {
64 TabControl = new TabControl();
65 Result.DialogPanel.Children.Add(TabControl);
66 DockPanel.SetDock(TabControl, Dock.Top);
67 }
68 else
69 {
70 ScrollViewer = new ScrollViewer()
71 {
72 VerticalScrollBarVisibility = ScrollBarVisibility.Auto
73 };
74
75 Result.DialogPanel.Children.Add(ScrollViewer);
76 DockPanel.SetDock(ScrollViewer, Dock.Top);
77
78 StackPanel = new StackPanel()
79 {
80 Margin = new Thickness(10, 10, 10, 10),
81 };
82
83 ScrollViewer.Content = StackPanel;
84 Container = StackPanel;
85 }
86
87 foreach (Networking.XMPP.DataForms.Layout.Page Page in Form.Pages)
88 {
89 if (!(TabControl is null))
90 {
91 TabItem = new TabItem()
92 {
93 Header = Page.Label
94 };
95
96 TabControl.Items.Add(TabItem);
97
98 ScrollViewer = new ScrollViewer()
99 {
100 VerticalScrollBarVisibility = ScrollBarVisibility.Auto
101 };
102
103 TabItem.Content = ScrollViewer;
104
105 StackPanel = new StackPanel()
106 {
107 Margin = new Thickness(10, 10, 10, 10)
108 };
109
110 ScrollViewer.Content = StackPanel;
111 Container = StackPanel;
112 }
113 else
114 TabItem = null;
115
116 if (!(Form.Instructions is null) && Form.Instructions.Length > 0)
117 {
118 foreach (string Row in Form.Instructions)
119 {
120 TextBlock TextBlock = new TextBlock()
121 {
122 TextWrapping = TextWrapping.Wrap,
123 Margin = new Thickness(0, 5, 0, 5),
124 Text = Row
125 };
126
127 Container.Children.Add(TextBlock);
128 Result.empty = false;
129 }
130 }
131
132 foreach (LayoutElement Element in Page.Elements)
133 {
134 Control = await Result.Layout(Container, Element, Form);
135 if (First is null)
136 First = Control;
137 }
138
139 if (!(TabControl is null) && TabControl.Items.Count == 1)
140 TabItem.Focus();
141 }
142
143 First?.Focus();
144
145 Result.CheckOkButtonEnabled();
146
147 return Result;
148 }
149
150 private async Task<Control> Layout(Panel Container, LayoutElement Element, DataForm Form)
151 {
152 if (Element is FieldReference FieldReference)
153 {
154 this.empty = false;
155 return await this.Layout(Container, FieldReference, Form);
156 }
157 else if (Element is Networking.XMPP.DataForms.Layout.TextElement TextElement)
158 {
159 this.empty = false;
160 this.Layout(Container, TextElement, Form);
161 }
162 else if (Element is Networking.XMPP.DataForms.Layout.Section Section)
163 {
164 this.empty = false;
165 return await this.Layout(Container, Section, Form);
166 }
167 else if (Element is ReportedReference ReportedReference)
168 {
169 if (this.Layout(Container, ReportedReference, Form))
170 this.empty = false;
171 }
172
173 return null;
174 }
175
176 private async Task<Control> Layout(Panel Container, Networking.XMPP.DataForms.Layout.Section Section, DataForm Form)
177 {
178 GroupBox GroupBox = new GroupBox();
179 Container.Children.Add(GroupBox);
180 GroupBox.Header = Section.Label;
181 GroupBox.Margin = new Thickness(5, 5, 5, 5);
182
183 StackPanel StackPanel = new StackPanel();
184 GroupBox.Content = StackPanel;
185 StackPanel.Margin = new Thickness(5, 5, 5, 5);
186
187 Control First = null;
188 Control Control;
189
190 foreach (LayoutElement Element in Section.Elements)
191 {
192 Control = await this.Layout(StackPanel, Element, Form);
193 if (First is null)
194 First = Control;
195 }
196
197 return First;
198 }
199
200 private void Layout(Panel Container, Networking.XMPP.DataForms.Layout.TextElement TextElement, DataForm _)
201 {
202 TextBlock TextBlock = new TextBlock()
203 {
204 TextWrapping = TextWrapping.Wrap,
205 Margin = new Thickness(0, 0, 0, 5),
206 Text = TextElement.Text
207 };
208
209 Container.Children.Add(TextBlock);
210 }
211
212 private async Task<Control> Layout(Panel Container, FieldReference FieldReference, DataForm Form)
213 {
215 if (Field is null)
216 return null;
217
218 Control Result = null;
219 bool MakeVisible = false;
220
221 if (Field.HasError)
222 MakeVisible = true;
223 else
225
227 Result = this.Layout(Container, TextSingleField, Form);
229 Result = this.Layout(Container, TextMultiField, Form);
231 Result = this.Layout(Container, TextPrivateField, Form);
232 else if (Field is BooleanField BooleanField)
233 Result = this.Layout(Container, BooleanField, Form);
235 Result = this.Layout(Container, ListSingleField, Form);
237 Result = this.Layout(Container, ListMultiField, Form);
238 else if (Field is FixedField FixedField)
239 this.Layout(Container, FixedField, Form);
241 Result = this.Layout(Container, JidMultiField, Form);
243 Result = this.Layout(Container, JidSingleField, Form);
244 else if (Field is MediaField MediaField)
245 await this.Layout(Container, MediaField, Form);
246
247 if (MakeVisible && this.makeVisible is null)
248 this.makeVisible = Result;
249
250 return Result;
251 }
252
253 private Control Layout(Panel Container, BooleanField Field, DataForm _)
254 {
255 TextBlock TextBlock = new TextBlock()
256 {
257 TextWrapping = TextWrapping.Wrap,
258 Text = Field.Label
259 };
260
261 if (Field.Required)
262 {
263 Run Run = new Run("*");
264 TextBlock.Inlines.Add(Run);
265 Run.Foreground = new SolidColorBrush(Colors.Red);
266 }
267
268 CheckBox CheckBox;
269
270 CheckBox = new CheckBox()
271 {
272 Name = VarToName(Field.Var),
273 Content = TextBlock,
274 Margin = new Thickness(0, 3, 0, 3),
275 IsEnabled = !Field.ReadOnly,
276 ToolTip = Field.Description
277 };
278
279 if (!CommonTypes.TryParse(Field.ValueString, out bool IsChecked))
280 CheckBox.IsChecked = null;
281 else
282 CheckBox.IsChecked = IsChecked;
283
284 if (Field.HasError)
285 CheckBox.Background = new SolidColorBrush(Colors.PeachPuff);
286 else if (Field.NotSame)
287 CheckBox.Background = new SolidColorBrush(Colors.LightGray);
288
289 CheckBox.Click += this.CheckBox_Click;
290
291 Container.Children.Add(CheckBox);
292
293 return CheckBox;
294 }
295
296 private async void CheckBox_Click(object Sender, RoutedEventArgs e)
297 {
298 try
299 {
300 if (!(Sender is CheckBox CheckBox))
301 return;
302
303 string Var = NameToVar(CheckBox.Name);
304 Field Field = this.form[Var];
305 if (Field is null)
306 return;
307
308 if (CheckBox.IsChecked.HasValue)
309 {
310 CheckBox.Background = null;
311 await Field.SetValue(CommonTypes.Encode(CheckBox.IsChecked.Value));
312 this.CheckOkButtonEnabled();
313 }
314 else
315 {
316 CheckBox.Background = new SolidColorBrush(Colors.LightGray);
317 await Field.SetValue(string.Empty);
318 }
319 }
320 catch (Exception ex)
321 {
322 Log.Exception(ex);
323 }
324 }
325
326 private void CheckOkButtonEnabled()
327 {
328 foreach (Field Field in this.form.Fields)
329 {
331 {
332 this.OkButton.IsEnabled = false;
333 return;
334 }
335
336 if (Field.Required && string.IsNullOrEmpty(Field.ValueString))
337 {
338 this.OkButton.IsEnabled = false;
339 return;
340 }
341 }
342
343 this.OkButton.IsEnabled = true;
344 }
345
346 private void Layout(Panel Container, FixedField Field, DataForm _)
347 {
348 TextBlock TextBlock = new TextBlock()
349 {
350 TextWrapping = TextWrapping.Wrap,
351 Margin = new Thickness(0, 5, 0, 5),
352 Text = Field.ValueString
353 };
354
355 Container.Children.Add(TextBlock);
356 }
357
358 private Control Layout(Panel Container, JidMultiField Field, DataForm _)
359 {
360 TextBox TextBox = this.LayoutTextBox(Container, Field);
361 TextBox.TextChanged += this.TextBox_TextChanged;
362 TextBox.AcceptsReturn = true;
363 TextBox.AcceptsTab = true;
364 TextBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
365
366 return TextBox;
367 }
368
369 private Control Layout(Panel Container, JidSingleField Field, DataForm _)
370 {
371 TextBox TextBox = this.LayoutTextBox(Container, Field);
372 TextBox.TextChanged += this.TextBox_TextChanged;
373
374 return TextBox;
375 }
376
377 private Control Layout(Panel Container, ListMultiField Field, DataForm _)
378 {
379 TextBlock TextBlock = new TextBlock()
380 {
381 TextWrapping = TextWrapping.Wrap,
382 Text = Field.Label
383 };
384
385 if (Field.Required)
386 {
387 Run Run = new Run("*");
388 TextBlock.Inlines.Add(Run);
389 Run.Foreground = new SolidColorBrush(Colors.Red);
390 }
391
392 GroupBox GroupBox = new GroupBox();
393 Container.Children.Add(GroupBox);
394 GroupBox.Name = VarToName(Field.Var);
395 GroupBox.Header = TextBlock;
396 GroupBox.ToolTip = Field.Description;
397 GroupBox.Margin = new Thickness(5, 5, 5, 5);
398
399 StackPanel StackPanel = new StackPanel();
400 GroupBox.Content = StackPanel;
401 StackPanel.Margin = new Thickness(5, 5, 5, 5);
402
403 string[] Values = Field.ValueStrings;
404 CheckBox CheckBox;
405
406 foreach (KeyValuePair<string, string> Option in Field.Options)
407 {
408 CheckBox = new CheckBox()
409 {
410 Content = Option.Key,
411 Tag = Option.Value,
412 Margin = new Thickness(0, 3, 0, 3),
413 IsEnabled = !Field.ReadOnly,
414 IsChecked = Array.IndexOf<string>(Values, Option.Value) >= 0
415 };
416
417 if (Field.HasError)
418 CheckBox.Background = new SolidColorBrush(Colors.PeachPuff);
419 else if (Field.NotSame)
420 CheckBox.Background = new SolidColorBrush(Colors.LightGray);
421
422 CheckBox.Click += this.MultiListCheckBox_Click;
423
424 StackPanel.Children.Add(CheckBox);
425 }
426
427 GroupBox.Tag = this.LayoutErrorLabel(StackPanel, Field);
428
429 return GroupBox;
430 }
431
432 private async void MultiListCheckBox_Click(object Sender, RoutedEventArgs e)
433 {
434 try
435 {
436 if (!(Sender is CheckBox CheckBox))
437 return;
438
439 if (!(CheckBox.Parent is StackPanel StackPanel))
440 return;
441
442 if (!(StackPanel.Parent is GroupBox GroupBox))
443 return;
444
445 string Var = NameToVar(GroupBox.Name);
446 Field Field = this.form[Var];
447 if (Field is null)
448 return;
449
450 List<string> Values = new List<string>();
451
452 foreach (UIElement Element in StackPanel.Children)
453 {
454 CheckBox = Element as CheckBox;
455 if (CheckBox is null)
456 continue;
457
458 if (CheckBox.IsChecked.HasValue && CheckBox.IsChecked.Value)
459 Values.Add((string)CheckBox.Tag);
460 }
461
462 await Field.SetValue(Values.ToArray());
463
464 TextBlock ErrorLabel = (TextBlock)GroupBox.Tag;
465 Brush Background;
466
467 if (Field.HasError)
468 {
469 Background = new SolidColorBrush(Colors.PeachPuff);
470 this.OkButton.IsEnabled = false;
471
472 if (!(ErrorLabel is null))
473 {
474 ErrorLabel.Text = Field.Error;
475 ErrorLabel.Visibility = Visibility.Visible;
476 }
477 }
478 else
479 {
480 Background = null;
481 this.CheckOkButtonEnabled();
482
483 if (!(ErrorLabel is null))
484 ErrorLabel.Visibility = Visibility.Collapsed;
485 }
486
487 foreach (UIElement Element in StackPanel.Children)
488 {
489 CheckBox = Element as CheckBox;
490 if (CheckBox is null)
491 continue;
492
493 CheckBox.Background = Background;
494 }
495 }
496 catch (Exception ex)
497 {
498 Log.Exception(ex);
499 }
500 }
501
502 private Control Layout(Panel Container, ListSingleField Field, DataForm _)
503 {
504 this.LayoutControlLabel(Container, Field);
505
506 ComboBox ComboBox = new ComboBox()
507 {
508 Name = VarToName(Field.Var),
509 IsReadOnly = Field.ReadOnly,
510 ToolTip = Field.Description,
511 Margin = new Thickness(0, 0, 0, 5)
512 };
513
514 if (Field.HasError)
515 ComboBox.Background = new SolidColorBrush(Colors.PeachPuff);
516 else if (Field.NotSame)
517 ComboBox.Background = new SolidColorBrush(Colors.LightGray);
518
519 ComboBoxItem Item;
520
521 if (!(Field.Options is null))
522 {
523 foreach (KeyValuePair<string, string> P in Field.Options)
524 {
525 Item = new ComboBoxItem()
526 {
527 Content = P.Key,
528 Tag = P.Value
529 };
530
531 ComboBox.Items.Add(Item);
532 }
533 }
534
535 if (Field.ValidationMethod is Networking.XMPP.DataForms.ValidationMethods.OpenValidation)
536 {
537 ComboBox.IsEditable = true;
538 ComboBox.Text = Field.ValueString;
539 ComboBox.AddHandler(System.Windows.Controls.Primitives.TextBoxBase.TextChangedEvent,
540 new TextChangedEventHandler(this.ComboBox_TextChanged));
541 }
542 else
543 {
544 string s = Field.ValueString;
545
546 ComboBox.IsEditable = false;
547 ComboBox.SelectionChanged += this.ComboBox_SelectionChanged;
548
549 if (!(Field.Options is null))
550 ComboBox.SelectedIndex = Array.FindIndex(Field.Options, (P) => P.Value.Equals(s));
551 }
552
553 Container.Children.Add(ComboBox);
554 ComboBox.Tag = this.LayoutErrorLabel(Container, Field);
555
556 return ComboBox;
557 }
558
559 private async void ComboBox_TextChanged(object Sender, TextChangedEventArgs e)
560 {
561 try
562 {
563 if (!(Sender is ComboBox ComboBox))
564 return;
565
566 string Var = NameToVar(ComboBox.Name);
567 Field Field = this.form[Var];
568 if (Field is null)
569 return;
570
571 TextBlock ErrorLabel = (TextBlock)ComboBox.Tag;
572 string s = ComboBox.Text;
573
574 if (ComboBox.SelectedItem is ComboBoxItem ComboBoxItem && ((string)ComboBoxItem.Content) == s)
575 s = (string)ComboBoxItem.Tag;
576
577 await Field.SetValue(s);
578
579 if (Field.HasError)
580 {
581 ComboBox.Background = new SolidColorBrush(Colors.PeachPuff);
582 this.OkButton.IsEnabled = false;
583
584 if (!(ErrorLabel is null))
585 {
586 ErrorLabel.Text = Field.Error;
587 ErrorLabel.Visibility = Visibility.Visible;
588 }
589 }
590 else
591 {
592 ComboBox.Background = null;
593
594 if (!(ErrorLabel is null))
595 ErrorLabel.Visibility = Visibility.Collapsed;
596
597 this.CheckOkButtonEnabled();
598 }
599 }
600 catch (Exception ex)
601 {
602 Log.Exception(ex);
603 }
604 }
605
606 private async void ComboBox_SelectionChanged(object Sender, SelectionChangedEventArgs e)
607 {
608 try
609 {
610 if (!(Sender is ComboBox ComboBox))
611 return;
612
613 string Var = NameToVar(ComboBox.Name);
614 Field Field = this.form[Var];
615 if (Field is null)
616 return;
617
618 TextBlock ErrorLabel = (TextBlock)ComboBox.Tag;
619 string Value;
620
621 if (!(ComboBox.SelectedItem is ComboBoxItem Item))
622 Value = string.Empty;
623 else
624 Value = (string)Item.Tag;
625
626 await Field.SetValue(Value);
627
628 if (Field.HasError)
629 {
630 ComboBox.Background = new SolidColorBrush(Colors.PeachPuff);
631 this.OkButton.IsEnabled = false;
632
633 if (!(ErrorLabel is null))
634 {
635 ErrorLabel.Text = Field.Error;
636 ErrorLabel.Visibility = Visibility.Visible;
637 }
638 return;
639 }
640 else
641 {
642 ComboBox.Background = null;
643
644 if (!(ErrorLabel is null))
645 ErrorLabel.Visibility = Visibility.Collapsed;
646
647 this.CheckOkButtonEnabled();
648 }
649 }
650 catch (Exception ex)
651 {
652 Log.Exception(ex);
653 }
654 }
655
656 private async Task Layout(Panel Container, MediaField Field, DataForm _)
657 {
658 MediaElement MediaElement;
659 Uri Uri = null;
660 Grade Best = Runtime.Inventory.Grade.NotAtAll;
661 Grade Grade;
662 bool IsImage = false;
663 bool IsVideo = false;
664 bool IsAudio = false;
665
666 bool TopMarginLaidOut = this.LayoutControlLabel(Container, Field);
667
668 foreach (KeyValuePair<string, Uri> P in Field.Media.URIs)
669 {
670 if (P.Key.StartsWith("image/"))
671 {
672 IsImage = true;
673 Uri = P.Value;
674 break;
675 }
676 else if (P.Key.StartsWith("video/"))
677 {
678 switch (P.Key.ToLower())
679 {
680 case "video/x-ms-asf":
681 case "video/x-ms-wvx":
682 case "video/x-ms-wm":
683 case "video/x-ms-wmx":
684 Grade = Grade.Perfect;
685 break;
686
687 case "video/mp4":
688 Grade = Grade.Excellent;
689 break;
690
691 case "video/3gp":
692 case "video/3gpp ":
693 case "video/3gpp2 ":
694 case "video/3gpp-tt":
695 case "video/h263":
696 case "video/h263-1998":
697 case "video/h263-2000":
698 case "video/h264":
699 case "video/h264-rcdo":
700 case "video/h264-svc":
701 Grade = Grade.Ok;
702 break;
703
704 default:
705 Grade = Grade.Barely;
706 break;
707 }
708
709 if (Grade > Best)
710 {
711 Best = Grade;
712 Uri = P.Value;
713 IsVideo = true;
714 }
715 }
716 else if (P.Key.StartsWith("audio/"))
717 {
718 switch (P.Key.ToLower())
719 {
720 case "audio/x-ms-wma":
721 case "audio/x-ms-wax":
722 case "audio/x-ms-wmv":
723 Grade = Grade.Perfect;
724 break;
725
726 case "audio/mp4":
727 case "audio/mpeg":
728 Grade = Grade.Excellent;
729 break;
730
731 case "audio/amr":
732 case "audio/amr-wb":
733 case "audio/amr-wb+":
734 case "audio/pcma":
735 case "audio/pcma-wb":
736 case "audio/pcmu":
737 case "audio/pcmu-wb":
738 Grade = Grade.Ok;
739 break;
740
741 default:
742 Grade = Grade.Barely;
743 break;
744 }
745
746 if (Grade > Best)
747 {
748 Best = Grade;
749 Uri = P.Value;
750 IsAudio = true;
751 }
752 }
753 }
754
755 if (IsImage)
756 {
757 BitmapImage BitmapImage = new System.Windows.Media.Imaging.BitmapImage();
758 BitmapImage.BeginInit();
759 try
760 {
761 if (!(Field.Media.Binary is null))
762 BitmapImage.UriSource = new Uri(await Waher.Content.Markdown.Model.Multimedia.ImageContent.GetTemporaryFile(Field.Media.Binary));
763 else if (!(Uri is null))
764 BitmapImage.UriSource = Uri;
765 else if (!string.IsNullOrEmpty(Field.Media.URL))
766 BitmapImage.UriSource = new Uri(Field.Media.URL);
767 }
768 finally
769 {
770 BitmapImage.EndInit();
771 }
772
773 Image Image = new Image()
774 {
775 Source = BitmapImage,
776 ToolTip = Field.Description,
777 Margin = new Thickness(0, TopMarginLaidOut ? 0 : 5, 0, 5)
778 };
779
780 if (Field.Media.Width.HasValue)
781 Image.Width = Field.Media.Width.Value;
782
783 if (Field.Media.Height.HasValue)
784 Image.Height = Field.Media.Height.Value;
785
786 Container.Children.Add(Image);
787 }
788 else if (IsVideo || IsAudio)
789 {
790 MediaElement = new MediaElement()
791 {
792 Source = Uri,
793 LoadedBehavior = MediaState.Manual,
794 ToolTip = Field.Description
795 };
796
797 Container.Children.Add(MediaElement);
798
799 if (IsVideo)
800 {
801 MediaElement.Margin = new Thickness(0, TopMarginLaidOut ? 0 : 5, 0, 5);
802
803 if (Field.Media.Width.HasValue)
804 MediaElement.Width = Field.Media.Width.Value;
805
806 if (Field.Media.Height.HasValue)
807 MediaElement.Height = Field.Media.Height.Value;
808 }
809
810 DockPanel ControlPanel = new DockPanel()
811 {
812 Width = 290
813 };
814
815 Container.Children.Add(ControlPanel);
816
817 Button Button = new Button()
818 {
819 Width = 50,
820 Height = 23,
821 Margin = new Thickness(0, 0, 5, 0),
822 Content = "<<",
823 Tag = MediaElement
824 };
825
826 ControlPanel.Children.Add(Button);
827 Button.Click += this.Rewind_Click;
828
829 Button = new Button()
830 {
831 Width = 50,
832 Height = 23,
833 Margin = new Thickness(5, 0, 5, 0),
834 Content = "Play",
835 Tag = MediaElement
836 };
837
838 ControlPanel.Children.Add(Button);
839 Button.Click += this.Play_Click;
840
841 Button = new Button()
842 {
843 Width = 50,
844 Height = 23,
845 Margin = new Thickness(5, 0, 5, 0),
846 Content = "Pause",
847 Tag = MediaElement
848 };
849
850 ControlPanel.Children.Add(Button);
851 Button.Click += this.Pause_Click;
852
853 Button = new Button()
854 {
855 Width = 50,
856 Height = 23,
857 Margin = new Thickness(5, 0, 5, 0),
858 Content = "Stop",
859 Tag = MediaElement
860 };
861
862 ControlPanel.Children.Add(Button);
863 Button.Click += this.Stop_Click;
864
865 Button = new Button()
866 {
867 Width = 50,
868 Height = 23,
869 Margin = new Thickness(5, 0, 0, 0),
870 Content = ">>",
871 Tag = MediaElement
872 };
873
874 ControlPanel.Children.Add(Button);
875 Button.Click += this.Forward_Click;
876
877 MediaElement.Play();
878 }
879 }
880
881 private void Rewind_Click(object Sender, RoutedEventArgs e)
882 {
883 Button Button = (Button)Sender;
884 MediaElement MediaElement = (MediaElement)Button.Tag;
885
886 if (!(MediaElement is null))
887 {
888 if (MediaElement.SpeedRatio >= 0)
889 MediaElement.SpeedRatio = -1;
890 else if (MediaElement.SpeedRatio > -32)
891 MediaElement.SpeedRatio *= 2;
892 }
893 }
894
895 private void Play_Click(object Sender, RoutedEventArgs e)
896 {
897 Button Button = (Button)Sender;
898 MediaElement MediaElement = (MediaElement)Button.Tag;
899
900 if (!(MediaElement is null))
901 {
902 if (MediaElement.Position >= MediaElement.NaturalDuration.TimeSpan)
903 {
904 MediaElement.Stop();
905 MediaElement.Position = TimeSpan.Zero;
906 }
907
908 MediaElement.Play();
909 }
910 }
911
912 private void Pause_Click(object Sender, RoutedEventArgs e)
913 {
914 Button Button = (Button)Sender;
915 MediaElement MediaElement = (MediaElement)Button.Tag;
916 MediaElement?.Pause();
917 }
918
919 private void Stop_Click(object Sender, RoutedEventArgs e)
920 {
921 Button Button = (Button)Sender;
922 MediaElement MediaElement = (MediaElement)Button.Tag;
923 MediaElement?.Stop();
924 }
925
926 private void Forward_Click(object Sender, RoutedEventArgs e)
927 {
928 Button Button = (Button)Sender;
929 MediaElement MediaElement = (MediaElement)Button.Tag;
930
931 if (!(MediaElement is null))
932 {
933 if (MediaElement.SpeedRatio <= 0)
934 MediaElement.SpeedRatio = 1;
935 else if (MediaElement.SpeedRatio < 32)
936 MediaElement.SpeedRatio *= 2;
937 }
938 }
939
940 private Control Layout(Panel Container, TextMultiField Field, DataForm _)
941 {
942 this.LayoutControlLabel(Container, Field);
943
945 {
946 Name = VarToName(Field.Var),
947 Text = Field.ValueString,
948 IsReadOnly = Field.ReadOnly,
949 ToolTip = Field.Description,
950 Margin = new Thickness(0, 0, 0, 5)
951 };
952
953 if (Field.HasError)
954 Editor.Background = new SolidColorBrush(Colors.PeachPuff);
955 else if (Field.NotSame)
956 Editor.Background = new SolidColorBrush(Colors.LightGray);
957
958 Container.Children.Add(Editor);
959 Editor.Tag = this.LayoutErrorLabel(Container, Field);
960
961 Editor.TextChanged += this.Editor_TextChanged;
962 Editor.BorderBrush = new SolidColorBrush(SystemColors.ActiveBorderColor);
963 Editor.BorderThickness = new Thickness(1);
964 Editor.Padding = new Thickness(5, 2, 5, 2);
965 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
966 Editor.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
967 Editor.HorizontalAlignment = HorizontalAlignment.Stretch;
968 Editor.Height = double.NaN;
969 Editor.Width = double.NaN;
970 Editor.Options.ShowSpaces = false;
971 Editor.Options.ShowTabs = false;
972
973 string ContentType = Field.ContentType?.ToLower() ?? PlainTextCodec.DefaultContentType;
974 string SyntaxHighlightingResource = null;
975
976 switch (ContentType)
977 {
979 Editor.WordWrap = true;
980 break;
981
982 case "text/markdown":
983 Editor.WordWrap = true;
984 SyntaxHighlightingResource = "Markdown.xshd";
985 break;
986
987 case "text/css":
988 Editor.FontFamily = new FontFamily("Courier New");
989 Editor.WordWrap = false;
990 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
991 SyntaxHighlightingResource = "CSS.xshd";
992 break;
993
994 case "text/sgml":
995 case "text/csv":
996 case "text/tab-separated-values":
997 case "application/x-turtle":
998 case "text/turtle":
999 case "application/sparql-query":
1000 Editor.FontFamily = new FontFamily("Courier New");
1001 Editor.WordWrap = false;
1002 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
1003 break;
1004
1005 case "application/json":
1006 case "text/x-json":
1007 Editor.FontFamily = new FontFamily("Courier New");
1008 Editor.WordWrap = false;
1009 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
1010 SyntaxHighlightingResource = "JSON.xshd";
1011 break;
1012
1013 case "text/xml":
1014 case "application/xml":
1015 case "text/xsl":
1016 Editor.FontFamily = new FontFamily("Courier New");
1017 Editor.WordWrap = false;
1018 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
1019 SyntaxHighlightingResource = "XML.xshd";
1020 break;
1021
1022 case "application/javascript":
1023 Editor.FontFamily = new FontFamily("Courier New");
1024 Editor.WordWrap = false;
1025 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
1026 SyntaxHighlightingResource = "JavaScript.xshd";
1027 break;
1028
1029 case "text/html":
1030 Editor.FontFamily = new FontFamily("Courier New");
1031 Editor.WordWrap = true;
1032 SyntaxHighlightingResource = "HTML.xshd";
1033 break;
1034
1035 case "text/richtext":
1036 Editor.FontFamily = new FontFamily("Courier New");
1037 Editor.WordWrap = false;
1038 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
1039 break;
1040
1041 case "application/x-webscript":
1042 Editor.FontFamily = new FontFamily("Courier New");
1043 Editor.WordWrap = false;
1044 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
1045 break;
1046
1047 case "text/x-cssx":
1048 Editor.FontFamily = new FontFamily("Courier New");
1049 Editor.WordWrap = false;
1050 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
1051 SyntaxHighlightingResource = "CSS.xshd";
1052 break;
1053
1054 default:
1055 Editor.FontFamily = new FontFamily("Courier New");
1056 Editor.WordWrap = false;
1057 Editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
1058
1059 if (ContentType.StartsWith("application/") && ContentType.EndsWith("+json"))
1060 SyntaxHighlightingResource = "JSON.xshd";
1061 else if (ContentType.StartsWith("application/") && ContentType.EndsWith("+xml"))
1062 SyntaxHighlightingResource = "XML.xshd";
1063
1064 break;
1065 }
1066
1067 if (!string.IsNullOrEmpty(SyntaxHighlightingResource))
1068 {
1069 // AvalodEdit Syntax Highlight files:
1070 //
1071 // CSS, HTML, JavaScript, JSON, XML.
1072 // Source: https://github.com/icsharpcode/AvalonEdit/tree/master/ICSharpCode.AvalonEdit/Highlighting/Resources
1073 //
1074 // Markdown:
1075 // Source: https://github.com/Trust-Anchor-Group/LegalLab/tree/main/LegalLab/Models/Design/AvalonExtensions
1076
1077 Type AppType = typeof(App);
1078
1079 using (Stream XshdStream = AppType.Assembly.GetManifestResourceStream(AppType.Namespace + ".Dialogs.AvalonExtensions." +
1080 SyntaxHighlightingResource))
1081 {
1082 using (XmlReader XshdReader = new XmlTextReader(XshdStream))
1083 {
1084 Editor.SyntaxHighlighting = HighlightingLoader.Load(XshdReader, HighlightingManager.Instance);
1085 }
1086 }
1087 }
1088
1089 return Editor;
1090 }
1091
1092 private Control Layout(Panel Container, TextPrivateField Field, DataForm _)
1093 {
1094 this.LayoutControlLabel(Container, Field);
1095
1096 PasswordBox PasswordBox = new PasswordBox()
1097 {
1098 Name = VarToName(Field.Var),
1099 Password = Field.ValueString,
1100 IsEnabled = !Field.ReadOnly,
1101 ToolTip = Field.Description,
1102 Margin = new Thickness(0, 0, 0, 5)
1103 };
1104
1105 if (Field.HasError)
1106 PasswordBox.Background = new SolidColorBrush(Colors.PeachPuff);
1107 else if (Field.NotSame)
1108 PasswordBox.Background = new SolidColorBrush(Colors.LightGray);
1109
1110 PasswordBox.PasswordChanged += this.PasswordBox_PasswordChanged;
1111
1112 Container.Children.Add(PasswordBox);
1113 PasswordBox.Tag = this.LayoutErrorLabel(Container, Field);
1114
1115 return PasswordBox;
1116 }
1117
1118 private async void PasswordBox_PasswordChanged(object Sender, RoutedEventArgs e)
1119 {
1120 try
1121 {
1122 if (!(Sender is PasswordBox PasswordBox))
1123 return;
1124
1125 string Var = NameToVar(PasswordBox.Name);
1126 Field Field = this.form[Var];
1127 if (Field is null)
1128 return;
1129
1130 await Field.SetValue(PasswordBox.Password);
1131
1132 TextBlock ErrorLabel = (TextBlock)PasswordBox.Tag;
1133
1134 if (Field.HasError)
1135 {
1136 PasswordBox.Background = new SolidColorBrush(Colors.PeachPuff);
1137 this.OkButton.IsEnabled = false;
1138
1139 if (!(ErrorLabel is null))
1140 {
1141 ErrorLabel.Text = Field.Error;
1142 ErrorLabel.Visibility = Visibility.Visible;
1143 }
1144 }
1145 else
1146 {
1147 PasswordBox.Background = null;
1148
1149 if (!(ErrorLabel is null))
1150 ErrorLabel.Visibility = Visibility.Collapsed;
1151
1152 this.CheckOkButtonEnabled();
1153 }
1154 }
1155 catch (Exception ex)
1156 {
1157 Log.Exception(ex);
1158 }
1159 }
1160
1161 private Control Layout(Panel Container, TextSingleField Field, DataForm _)
1162 {
1163 TextBox TextBox = this.LayoutTextBox(Container, Field);
1164 TextBox.TextChanged += this.TextBox_TextChanged;
1165
1166 return TextBox;
1167 }
1168
1169 private TextBox LayoutTextBox(Panel Container, Field Field)
1170 {
1171 this.LayoutControlLabel(Container, Field);
1172
1173 TextBox TextBox = new TextBox()
1174 {
1175 Name = VarToName(Field.Var),
1176 Text = Field.ValueString,
1177 IsReadOnly = Field.ReadOnly,
1178 ToolTip = Field.Description,
1179 Margin = new Thickness(0, 0, 0, 5)
1180 };
1181
1182 if (Field.HasError)
1183 TextBox.Background = new SolidColorBrush(Colors.PeachPuff);
1184 else if (Field.NotSame)
1185 TextBox.Background = new SolidColorBrush(Colors.LightGray);
1186
1187 Container.Children.Add(TextBox);
1188 TextBox.Tag = this.LayoutErrorLabel(Container, Field);
1189
1190 return TextBox;
1191 }
1192
1193 private TextBlock LayoutErrorLabel(Panel Container, Field Field)
1194 {
1195 TextBlock ErrorLabel = new TextBlock()
1196 {
1197 TextWrapping = TextWrapping.Wrap,
1198 Margin = new Thickness(0, 0, 0, 5),
1199 Text = Field.Error,
1200 Foreground = new SolidColorBrush(Colors.Red),
1201 FontWeight = FontWeights.Bold,
1202 Visibility = Field.HasError ? Visibility.Visible : Visibility.Collapsed
1203 };
1204
1205 Container.Children.Add(ErrorLabel);
1206
1207 return ErrorLabel;
1208 }
1209
1210 private bool LayoutControlLabel(Panel Container, Field Field)
1211 {
1212 if (string.IsNullOrEmpty(Field.Label) && !Field.Required)
1213 return false;
1214 else
1215 {
1216 TextBlock TextBlock = new TextBlock()
1217 {
1218 TextWrapping = TextWrapping.Wrap,
1219 Text = Field.Label,
1220 Margin = new Thickness(0, 5, 0, 0)
1221 };
1222
1223 Container.Children.Add(TextBlock);
1224
1225 if (Field.Required)
1226 {
1227 Run Run = new Run("*");
1228 TextBlock.Inlines.Add(Run);
1229 Run.Foreground = new SolidColorBrush(Colors.Red);
1230 }
1231
1232 return true;
1233 }
1234 }
1235
1236 private async void TextBox_TextChanged(object Sender, TextChangedEventArgs e)
1237 {
1238 try
1239 {
1240 if (!(Sender is TextBox TextBox))
1241 return;
1242
1243 string Var = NameToVar(TextBox.Name);
1244 Field Field = this.form[Var];
1245 if (Field is null)
1246 return;
1247
1248 TextBlock ErrorLabel = (TextBlock)TextBox.Tag;
1249
1250 await Field.SetValue(TextBox.Text.Replace("\r\n", "\n").Replace("\r", "\n").Split('\n'));
1251
1252 if (Field.HasError)
1253 {
1254 TextBox.Background = new SolidColorBrush(Colors.PeachPuff);
1255 this.OkButton.IsEnabled = false;
1256 if (!(ErrorLabel is null))
1257 {
1258 ErrorLabel.Text = Field.Error;
1259 ErrorLabel.Visibility = Visibility.Visible;
1260 }
1261 }
1262 else
1263 {
1264 TextBox.Background = null;
1265
1266 if (!(ErrorLabel is null))
1267 ErrorLabel.Visibility = Visibility.Collapsed;
1268
1269 this.CheckOkButtonEnabled();
1270 }
1271 }
1272 catch (Exception ex)
1273 {
1274 Log.Exception(ex);
1275 }
1276 }
1277
1278 private async void Editor_TextChanged(object Sender, EventArgs e)
1279 {
1280 try
1281 {
1282 if (!(Sender is NonScrollingTextEditor Editor))
1283 return;
1284
1285 string Var = NameToVar(Editor.Name);
1286 Field Field = this.form[Var];
1287 if (Field is null)
1288 return;
1289
1290 TextBlock ErrorLabel = (TextBlock)Editor.Tag;
1291
1292 await Field.SetValue(Editor.Text.Replace("\r\n", "\n").Replace("\r", "\n").Split('\n'));
1293
1294 if (Field.HasError)
1295 {
1296 Editor.Background = new SolidColorBrush(Colors.PeachPuff);
1297 this.OkButton.IsEnabled = false;
1298 if (!(ErrorLabel is null))
1299 {
1300 ErrorLabel.Text = Field.Error;
1301 ErrorLabel.Visibility = Visibility.Visible;
1302 }
1303 }
1304 else
1305 {
1306 Editor.Background = null;
1307
1308 if (!(ErrorLabel is null))
1309 ErrorLabel.Visibility = Visibility.Collapsed;
1310
1311 this.CheckOkButtonEnabled();
1312 }
1313 }
1314 catch (Exception ex)
1315 {
1316 Log.Exception(ex);
1317 }
1318 }
1319
1320 private bool Layout(Panel Container, ReportedReference _, DataForm Form)
1321 {
1322 if (Form.Records.Length == 0 || Form.Header.Length == 0)
1323 return false;
1324
1325 Dictionary<string, int> VarIndex = new Dictionary<string, int>();
1326 ColumnDefinition ColumnDefinition;
1327 RowDefinition RowDefinition;
1328 TextBlock TextBlock;
1329 int i, j;
1330
1331 Brush BorderBrush = new SolidColorBrush(Colors.Gray);
1332 Brush Bg1 = new SolidColorBrush(Color.FromArgb(0x20, 0x40, 0x40, 0x40));
1333 Brush Bg2 = new SolidColorBrush(Color.FromArgb(0x10, 0x80, 0x80, 0x80));
1334 Border Border;
1335 Grid Grid = new Grid();
1336 Container.Children.Add(Grid);
1337
1338 i = 0;
1339 foreach (Field Field in Form.Header)
1340 {
1341 ColumnDefinition = new ColumnDefinition()
1342 {
1343 Width = GridLength.Auto
1344 };
1345
1346 Grid.ColumnDefinitions.Add(ColumnDefinition);
1347
1348 VarIndex[Field.Var] = i++;
1349 }
1350
1351 RowDefinition = new RowDefinition()
1352 {
1353 Height = GridLength.Auto
1354 };
1355
1356 Grid.RowDefinitions.Add(RowDefinition);
1357
1358 foreach (Field[] Row in Form.Records)
1359 {
1360 RowDefinition = new RowDefinition()
1361 {
1362 Height = GridLength.Auto
1363 };
1364
1365 Grid.RowDefinitions.Add(RowDefinition);
1366 }
1367
1368 foreach (Field Field in Form.Header)
1369 {
1370 if (!VarIndex.TryGetValue(Field.Var, out i))
1371 continue;
1372
1373 Border = new Border();
1374 Grid.Children.Add(Border);
1375
1376 Grid.SetColumn(Border, i);
1377 Grid.SetRow(Border, 0);
1378
1379 Border.BorderBrush = BorderBrush;
1380 Border.BorderThickness = new Thickness(1);
1381 Border.Padding = new Thickness(5, 1, 5, 1);
1382 Border.Background = Bg1;
1383
1384 TextBlock = new TextBlock()
1385 {
1386 FontWeight = FontWeights.Bold,
1387 Text = Field.Label
1388 };
1389
1390 Border.Child = TextBlock;
1391 }
1392
1393 j = 0;
1394 foreach (Field[] Row in Form.Records)
1395 {
1396 j++;
1397
1398 foreach (Field Field in Row)
1399 {
1400 if (!VarIndex.TryGetValue(Field.Var, out i))
1401 continue;
1402
1403 Border = new Border();
1404 Grid.Children.Add(Border);
1405
1406 Grid.SetColumn(Border, i);
1407 Grid.SetRow(Border, j);
1408
1409 Border.BorderBrush = BorderBrush;
1410 Border.BorderThickness = new Thickness(1);
1411 Border.Padding = new Thickness(5, 1, 5, 1);
1412
1413 if ((j & 1) == 1)
1414 Border.Background = Bg2;
1415 else
1416 Border.Background = Bg1;
1417
1418 TextBlock = new TextBlock()
1419 {
1420 Text = Field.ValueString
1421 };
1422
1423 Border.Child = TextBlock;
1424 }
1425 }
1426
1427 return true;
1428 }
1429
1430 private async void OkButton_Click(object Sender, RoutedEventArgs e)
1431 {
1432 try
1433 {
1434 await this.form.Submit();
1435
1436 this.DialogResult = true;
1437 }
1438 catch (Exception ex)
1439 {
1440 Log.Exception(ex);
1441 }
1442 }
1443
1444 private async void CancelButton_Click(object Sender, RoutedEventArgs e)
1445 {
1446 try
1447 {
1448 await this.form.Cancel();
1449
1450 this.DialogResult = false;
1451 }
1452 catch (Exception ex)
1453 {
1454 Log.Exception(ex);
1455 }
1456 }
1457
1458 private void Window_Activated(object Sender, EventArgs e)
1459 {
1460 if (!(this.makeVisible is null))
1461 {
1462 LinkedList<FrameworkElement> List = new LinkedList<FrameworkElement>();
1463
1464 while (!(this.makeVisible is null))
1465 {
1466 List.AddFirst(this.makeVisible);
1467 this.makeVisible = this.makeVisible.Parent as FrameworkElement;
1468 }
1469
1470 foreach (FrameworkElement E in List)
1471 {
1472 if (E.Focusable)
1473 E.Focus();
1474 else
1475 E.BringIntoView();
1476 }
1477 }
1478 }
1479
1480 private static string VarToName(string Var)
1481 {
1482 return "Form_" + Var.Replace("#", "__GATO__");
1483 }
1484
1485 private static string NameToVar(string Name)
1486 {
1487 return Name.Substring(5).Replace("__GATO__", "#");
1488 }
1489
1490 // TODO: Color picker.
1491 // TODO: Dynamic forms & post back
1492
1493 }
1494}
Interaction logic for App.xaml
Definition: App.xaml.cs:9
Avalon editor that does not capture mouse wheel (scrolling) events.
Interaction logic for ParameterDialog.xaml
void InitializeComponent()
InitializeComponent
static async Task< ParameterDialog > CreateAsync(DataForm Form)
Interaction logic for ParameterDialog.xaml
Helps with parsing of commong data types.
Definition: CommonTypes.cs:13
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:594
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Definition: CommonTypes.cs:46
static Task< string > GetTemporaryFile(byte[] BinaryImage)
Stores an image in binary form as a temporary file. Files will be deleted when application closes.
Definition: ImageContent.cs:88
Plain text encoder/decoder.
const string DefaultContentType
text/plain
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1647
Implements support for data forms. Data Forms are defined in the following XEPs:
Definition: DataForm.cs:42
string[] Instructions
Form Instructions
Definition: DataForm.cs:732
bool HasPages
If the form has pages.
Definition: DataForm.cs:759
Field[][] Records
Records in a report result form.
Definition: DataForm.cs:754
Field[] Header
Header fields in a report result form.
Definition: DataForm.cs:749
Base class for form fields
Definition: Field.cs:16
async Task< object > SetValue(string Value)
Sets the value of the field.
Definition: Field.cs:228
bool HasError
If the field has an error. Any error message is available in the Error property.
Definition: Field.cs:135
string Var
Variable name
Definition: Field.cs:81
bool ReadOnly
Flags the field as being read-only.
Definition: Field.cs:145
string Error
If not null, flags the field as having an error.
Definition: Field.cs:127
virtual object[] Validate(params string[] Value)
Validates field input. The Field.Error property will reflect any errors found.
Definition: Field.cs:180
ValidationMethod ValidationMethod
Validation Method
Definition: Field.cs:121
bool Required
If the field is required.
Definition: Field.cs:91
bool NotSame
Flags the field as having an undefined or uncertain value.
Definition: Field.cs:150
string ValueString
Value as a single string. If field contains multiple values, they will be concatenated into a single ...
Definition: Field.cs:101
string Description
Description
Definition: Field.cs:111
string[] ValueStrings
Values for the field (string representations).
Definition: Field.cs:96
KeyValuePair< string, string >[] Options
Options, as (Key=M2H Label, Value=M2M Value) pairs.
Definition: Field.cs:106
Base class for all layout elements in a data form layout.
Definition: LayoutElement.cs:9
Class managing a page in a data form layout.
Definition: Page.cs:11
Class managing a reported section reference.
Class managing a section within a page in a data form layout.
Definition: Section.cs:13
LayoutElement[] Elements
Embedded layout elements.
Definition: Section.cs:118
HorizontalAlignment
Horizontal alignment
Definition: Cell.cs:14
Grade
Grade enumeration
Definition: Grade.cs:7
ContentType
DTLS Record content type.
Definition: Enumerations.cs:11
Definition: App.xaml.cs:4