Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
PageModel.cs
4using Waher.Content;
5using Microsoft.Maui.Controls.Shapes;
6
8{
12 public class PageModel
13 {
14 private readonly XmppFormViewModel model;
15 private readonly DataForm form;
16 private readonly Layout.Page page;
17
18 public PageModel(XmppFormViewModel Model, Layout.Page Page)
19 {
20 this.model = Model;
21 this.page = Page;
22 this.form = this.page.Form;
23 }
24
25 public string Label => this.page.Label;
26
27 public bool HasLabel => !string.IsNullOrEmpty(this.page.Label);
28
29 public View Content => this.BuildContent(this.page.Elements);
30
31 private VerticalStackLayout BuildContent(Layout.LayoutElement[] Elements)
32 {
33 VerticalStackLayout Result = new VerticalStackLayout();
34
35 foreach (Layout.LayoutElement Element in Elements)
36 {
37 if (this.BuildContent(Element) is View view)
38 Result.Children.Add(view);
39 }
40
41 return Result;
42 }
43
44 private object? BuildContent(Layout.LayoutElement Element)
45 {
46 if (Element is Layout.FieldReference FieldRef)
47 {
48 Field Field = FieldRef.Form[FieldRef.Var];
49 if (Field is null)
50 return null;
51
52 if (Field is BooleanField)
53 {
54 HorizontalStackLayout Layout = [];
55
56 CheckBox CheckBox = new()
57 {
58 IsChecked = CommonTypes.TryParse(Field.ValueString, out bool b) && b,
59 IsEnabled = !Field.ReadOnly,
60 StyleId = Field.Var,
61 VerticalOptions = LayoutOptions.Center,
62 BackgroundColor = BackgroundColor(Field)
63 };
64
65 CheckBox.CheckedChanged += this.CheckBox_CheckedChanged;
66
67 Layout.Children.Add(CheckBox);
68 Layout.Children.Add(new Label()
69 {
70 Text = Field.Label,
71 Style = AppStyles.KeyLabel,
72 LineBreakMode = LineBreakMode.WordWrap,
73 VerticalOptions = LayoutOptions.Center
74 });
75
76 return Layout;
77 }
78 else if (Field is FixedField FixedField)
79 {
80 return new Label()
81 {
83 Style = AppStyles.InfoLabel,
84 LineBreakMode = LineBreakMode.WordWrap
85 };
86 }
88 {
89 VerticalStackLayout Layout = [];
90
91 Layout.Children.Add(new Label()
92 {
93 Text = Field.Label,
94 Style = AppStyles.KeyLabel,
95 LineBreakMode = LineBreakMode.WordWrap
96 });
97
98 Entry Entry = new()
99 {
100 Text = Field.ValueString,
101 IsEnabled = !Field.ReadOnly,
102 StyleId = Field.Var,
103 BackgroundColor = BackgroundColor(Field),
104 IsPassword = Field is TextPrivateField
105 };
106
107 Entry.TextChanged += this.Entry_TextChanged;
108
109 Layout.Children.Add(Entry);
110
111 return Layout;
112 }
113 else if (Field is TextMultiField || Field is JidMultiField)
114 {
115 VerticalStackLayout Layout = [];
116
117 Layout.Children.Add(new Label()
118 {
119 Text = Field.Label,
120 Style = AppStyles.KeyLabel,
121 LineBreakMode = LineBreakMode.WordWrap
122 });
123
124 Editor Editor = new()
125 {
126 Text = Field.ValueString,
127 IsEnabled = !Field.ReadOnly,
128 StyleId = Field.Var,
129 BackgroundColor = BackgroundColor(Field)
130 };
131
132 Editor.TextChanged += this.Editor_TextChanged;
133
134 Layout.Children.Add(Editor);
135
136 return Layout;
137 }
139 {
140 VerticalStackLayout Layout = [];
141
142 Layout.Children.Add(new Label()
143 {
144 Text = Field.Label,
145 Style = AppStyles.KeyLabel,
146 LineBreakMode = LineBreakMode.WordWrap
147 });
148
149 Picker Picker = new()
150 {
151 Title = Field.Description,
152 IsEnabled = !Field.ReadOnly,
153 StyleId = Field.Var,
154 BackgroundColor = BackgroundColor(Field)
155 };
156
157 if (Field?.Options is not null)
158 {
159 foreach (KeyValuePair<string, string> Option in Field.Options)
160 Picker.Items.Add(Option.Key);
161 }
162
163 Picker.SelectedItem = Field?.ValueString;
164 Picker.SelectedIndexChanged += this.Picker_SelectedIndexChanged;
165
166 Layout.Children.Add(Picker);
167
168 return Layout;
169 }
170 else if (Field is ListMultiField)
171 {
172 VerticalStackLayout Layout = [];
173
174 Layout.Children.Add(new Label()
175 {
176 Text = Field.Label,
177 Style = AppStyles.KeyLabel,
178 LineBreakMode = LineBreakMode.WordWrap
179 });
180
181 if (Field.Options is not null)
182 {
183 Dictionary<string, bool> Selected = [];
184
185 if (Field.ValueStrings is not null)
186 {
187 foreach (string s in Field.ValueStrings)
188 Selected[s] = true;
189 }
190
191 foreach (KeyValuePair<string, string> Option in Field.Options)
192 {
193 HorizontalStackLayout Layout2 = [];
194
195 CheckBox CheckBox = new()
196 {
197 IsChecked = Selected.ContainsKey(Option.Value),
198 IsEnabled = !Field.ReadOnly,
199 StyleId = Field.Var + " | " + Option.Value,
200 VerticalOptions = LayoutOptions.Center,
201 BackgroundColor = BackgroundColor(Field)
202 };
203
204 CheckBox.CheckedChanged += this.MultiCheckBox_CheckedChanged;
205
206 Layout2.Children.Add(CheckBox);
207 Layout2.Children.Add(new Label()
208 {
209 Text = Option.Key,
210 Style = AppStyles.KeyLabel,
211 LineBreakMode = LineBreakMode.WordWrap,
212 VerticalOptions = LayoutOptions.Center
213 });
214
215 Layout.Children.Add(Layout2);
216 }
217 }
218
219 return Layout;
220 }
221 else if (Field is MediaField MediaField)
222 {
224
225 if (string.IsNullOrEmpty(Media.ContentType) || Media.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
226 {
227 VerticalStackLayout Layout = [];
228
229 Layout.Children.Add(new Label()
230 {
231 Text = Field.Label,
232 Style = AppStyles.KeyLabel,
233 LineBreakMode = LineBreakMode.WordWrap
234 });
235
236 ImageSource? Source;
237
238 if (Media.Binary is not null)
239 Source = ImageSource.FromStream(() => new MemoryStream(Media.Binary));
240 else if (!string.IsNullOrEmpty(Media.URL) && Uri.TryCreate(Media.URL, UriKind.Absolute, out Uri? ParsedUrl))
241 Source = ImageSource.FromUri(ParsedUrl);
242 else
243 Source = null;
244
245 if (Source is not null)
246 {
247 Image Image = new()
248 {
249 Source = Source,
250 HorizontalOptions = LayoutOptions.Center,
251 VerticalOptions = LayoutOptions.Start
252 };
253
254 Layout.Children.Add(Image);
255 }
256
257 return Layout;
258 }
259 else
260 return null; // TODO: audio, video
261 }
262 else
263 return null;
264 }
265 else if (Element is Layout.Section Section)
266 {
267 VerticalStackLayout Layout = [];
268
269 if (!string.IsNullOrEmpty(Section.Label))
270 {
271 Layout.Children.Add(new Label()
272 {
273 Text = Section.Label,
275 LineBreakMode = LineBreakMode.WordWrap
276 });
277 }
278
279 foreach (Layout.LayoutElement Element2 in Section.Elements)
280 {
281 object? Content = this.BuildContent(Element2);
282
283 if (Content is View View)
284 Layout.Children.Add(View);
285 }
286
287 Border Frame = new()
288 {
290 Padding = new Thickness(10),
291 StrokeShape = new RoundRectangle
292 {
293 CornerRadius = 5
294 },
295 Content = Layout
296 };
297
298 return Frame;
299 }
300 else if (Element is Layout.TextElement Text)
301 {
302 return new Label()
303 {
304 Text = Text.Text,
305 Style = AppStyles.InfoLabel,
306 LineBreakMode = LineBreakMode.WordWrap
307 };
308 }
309 else
310 return null;
311 }
312
313 private static Color? BackgroundColor(Field F)
314 {
315 if (F.HasError)
317 else if (F.NotSame)
319 else
320 return null;
321 }
322
323 private void CheckBox_CheckedChanged(object? sender, CheckedChangedEventArgs e)
324 {
325 if (sender is not CheckBox CheckBox)
326 return;
327
328 string Var = CheckBox.StyleId;
329 Field Field = this.form[Var];
330 if (Field is null)
331 return;
332
334
335 CheckBox.BackgroundColor = BackgroundColor(Field);
336
337 this.model.ValidateForm();
338 }
339
340 private void Entry_TextChanged(object? sender, TextChangedEventArgs e)
341 {
342 if (sender is not Entry Entry)
343 return;
344
345 string Var = Entry.StyleId;
346 Field Field = this.form[Var];
347 if (Field is null)
348 return;
349
350 Field.SetValue(e.NewTextValue);
351
352 Entry.BackgroundColor = BackgroundColor(Field);
353
354 this.model.ValidateForm();
355 }
356
357 private void Editor_TextChanged(object? sender, TextChangedEventArgs e)
358 {
359 if (sender is not Editor Editor)
360 return;
361
362 string Var = Editor.StyleId;
363 Field Field = this.form[Var];
364 if (Field is null)
365 return;
366
367 Field.SetValue(e.NewTextValue);
368
369 Editor.BackgroundColor = BackgroundColor(Field);
370
371 this.model.ValidateForm();
372 }
373
374 private void Picker_SelectedIndexChanged(object? sender, EventArgs e)
375 {
376 if (sender is not Picker Picker)
377 return;
378
379 string Var = Picker.StyleId;
380 Field Field = this.form[Var];
381 if (Field is null)
382 return;
383
384 string s = Picker.SelectedItem?.ToString() ?? string.Empty;
385
386 if (Field.Options is not null)
387 {
388 foreach (KeyValuePair<string, string> P in Field.Options)
389 {
390 if (s == P.Key)
391 {
392 s = P.Value;
393 break;
394 }
395 }
396 }
397
398 Field.SetValue(s);
399
400 Picker.BackgroundColor = BackgroundColor(Field);
401
402 this.model.ValidateForm();
403 }
404
405 private void MultiCheckBox_CheckedChanged(object? sender, CheckedChangedEventArgs e)
406 {
407 if (sender is not CheckBox CheckBox)
408 return;
409
410 string Var = CheckBox.StyleId;
411 int i = Var.IndexOf(" | ", StringComparison.InvariantCultureIgnoreCase);
412 if (i < 0)
413 return;
414
415 string Value = Var[(i + 3)..];
416 Var = Var[..i];
417
418 Field Field = this.form[Var];
419 if (Field is null)
420 return;
421
422 List<string> Values = [];
423 if (Field.ValueStrings is not null)
424 Values.AddRange(Field.ValueStrings);
425
426 if (e.Value)
427 {
428 i = Values.IndexOf(Value);
429 if (i < 0)
430 Values.Add(Value);
431 }
432 else
433 Values.Remove(Value);
434
435 Field.SetValue([.. Values]);
436
437 CheckBox.BackgroundColor = BackgroundColor(Field);
438
439 this.model.ValidateForm();
440 }
441
442 }
443}
Static class that gives access to app-specific themed colors. All colors are fetched directly from th...
Definition: AppColors.cs:8
static Color PrimaryForeground
Primary foreground color.
Definition: AppColors.cs:143
static Color ErrorBackground
Error Background Color.
Definition: AppColors.cs:179
static Color ButtonUniversalbgInactiveWL
DisabledFilledButton background color.
Definition: AppColors.cs:167
Static class that gives access to app-specific styles
Definition: AppStyles.cs:12
static Style SectionTitleLabel
Style of section title labels
Definition: AppStyles.cs:205
static Style InfoLabel
Style of information labels
Definition: AppStyles.cs:265
static Style KeyLabel
Style of key labels
Definition: AppStyles.cs:217
The view model to bind to for when displaying the calculator.
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:596
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Definition: CommonTypes.cs:48
Implements support for data forms. Data Forms are defined in the following XEPs:
Definition: DataForm.cs:42
Base class for form fields
Definition: Field.cs:17
async Task< object > SetValue(string Value)
Sets the value of the field.
Definition: Field.cs:229
DataForm Form
Data Form containing the field.
Definition: Field.cs:74
string Var
Variable name
Definition: Field.cs:82
bool ReadOnly
Flags the field as being read-only.
Definition: Field.cs:146
string ValueString
Value as a single string. If field contains multiple values, they will be concatenated into a single ...
Definition: Field.cs:102
string Description
Description
Definition: Field.cs:112
string[] ValueStrings
Values for the field (string representations).
Definition: Field.cs:97
KeyValuePair< string, string >[] Options
Options, as (Key=M2H Label, Value=M2M Value) pairs.
Definition: Field.cs:107
Media Media
Media content to display in the field.
Definition: MediaField.cs:69
Class managing a page in a data form layout.
Definition: Page.cs:11
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
Class containing information about media content in a data form.
Definition: Media.cs:18
string URL
Any web-based URL for the media.
Definition: Media.cs:137
string ContentType
Content-Type of data, if available.
Definition: Media.cs:128
byte[] Binary
Binary content, if available in the form.
Definition: Media.cs:119
Definition: App.xaml.cs:4