4using System.Collections.Generic;
9using System.Threading.Tasks;
11using System.Windows.Controls;
12using System.Windows.Data;
13using System.Windows.Markup;
14using System.Windows.Media;
15using System.Windows.Media.Imaging;
17using System.Xml.Schema;
38 private readonly Dictionary<string, (DataTable,
Column[], ListView)> tables =
new Dictionary<
string, (DataTable,
Column[], ListView)>();
39 private readonly LinkedList<ThreadStart> guiQueue =
new LinkedList<ThreadStart>();
40 private readonly LinkedList<ReportElement> elements =
new LinkedList<ReportElement>();
41 private readonly TextBlock headerLabel;
44 private StackPanel currentPanel;
50 this.headerLabel = HeaderLabel;
59 if (!(Result.query is
null))
61 Result.query.Aborted += Result.Query_Aborted;
62 Result.query.EventMessageReceived += Result.Query_EventMessageReceived;
63 Result.query.NewTitle += Result.Query_NewTitle;
64 Result.query.SectionAdded += Result.Query_SectionAdded;
65 Result.query.SectionCompleted += Result.Query_SectionCompleted;
66 Result.query.Started += Result.Query_Started;
67 Result.query.Done += Result.Query_Done;
68 Result.query.StatusMessageReceived += Result.Query_StatusMessageReceived;
69 Result.query.TableAdded += Result.Query_TableAdded;
70 Result.query.TableCompleted += Result.Query_TableCompleted;
71 Result.query.TableUpdated += Result.Query_TableUpdated;
72 Result.query.ObjectAdded += Result.Query_ObjectAdded;
77 Result.currentPanel = Result.ReportPanel;
85 private void UpdateGui(ThreadStart P)
91 Call = this.guiQueue.First is
null;
92 this.guiQueue.AddLast(P);
99 private Task UpdateGuiSta()
108 if (this.guiQueue.First is
null)
109 return Task.CompletedTask;
111 P = this.guiQueue.First.Value;
112 this.guiQueue.RemoveFirst();
113 More = !(this.guiQueue.First is
null);
127 return Task.CompletedTask;
130 private void StatusMessage(
string Message)
132 this.UpdateGui(
new ThreadStart(() =>
134 this.Status.Content = Message;
140 this.StatusMessage(
"Execution started.");
141 return Task.CompletedTask;
146 this.StatusMessage(
"Execution completed.");
147 return Task.CompletedTask;
152 this.StatusMessage(
"Execution aborted.");
153 return Task.CompletedTask;
159 return Task.CompletedTask;
164 this.UpdateGui(
new ThreadStart(() =>
169 return Task.CompletedTask;
176 this.elements.AddLast(
Event);
182 switch (
Event.EventType)
186 FgColor = Brushes.Black;
187 BgColor = Brushes.White;
191 FgColor = Brushes.Black;
192 BgColor = Brushes.Yellow;
196 FgColor = Brushes.Yellow;
197 BgColor = Brushes.Red;
201 FgColor = Brushes.Yellow;
202 BgColor = Brushes.DarkRed;
206 this.currentPanel.Children.Add(
new TextBlock()
208 Text =
Event.EventMessage,
209 Margin =
new Thickness(0, 0, 0, 6),
210 Foreground = FgColor,
211 Background = BgColor,
212 FontFamily =
new FontFamily(
"Courier New")
218 this.UpdateGui(
new ThreadStart(() =>
220 this.headerLabel.Text = this.query.
Title;
223 return Task.CompletedTask;
228 this.UpdateGui(
new ThreadStart(() =>
233 return Task.CompletedTask;
240 this.elements.AddLast(
Event);
243 StackPanel Section =
new StackPanel()
245 Margin =
new Thickness(16, 8, 16, 8)
248 this.currentPanel.Children.Add(Section);
249 this.currentPanel = Section;
251 Section.Children.Add(
new TextBlock()
255 FontWeight = FontWeights.Bold,
256 Margin =
new Thickness(0, 0, 0, 12)
262 this.UpdateGui(
new ThreadStart(() =>
267 return Task.CompletedTask;
274 this.elements.AddLast(
Event);
277 this.currentPanel = this.currentPanel.Parent as StackPanel;
278 if (this.currentPanel is
null)
279 this.currentPanel = this.ReportPanel;
284 this.UpdateGui(
new ThreadStart(() =>
290 return Task.CompletedTask;
297 this.elements.AddLast(
Event);
302 if (!this.tables.ContainsKey(
Event.TableId))
305 GridView GridView =
new GridView();
313 GridView.Columns.Add(
new GridViewColumn()
320 ListView TableView =
new ListView()
322 ItemsSource =
Table.DefaultView,
328 this.currentPanel.Children.Add(TableView);
333 this.StatusMessage(ex.Message);
339 this.UpdateGui(
new ThreadStart(() =>
345 return Task.CompletedTask;
350 if (this.tables.TryGetValue(
Event.TableId, out (DataTable,
Column[], ListView) P))
354 this.elements.AddLast(
Event);
357 DataTable
Table = P.Item1;
358 Column[] Columns = P.Item2;
361 int i, c = Columns.Length;
366 DataRow Row =
Table.NewRow();
369 for (i = 0; i < d; i++)
382 else if (Obj is
double dbl)
389 else if (Obj is decimal dec)
396 else if (Obj is
float f)
403 else if (Obj is DateTime DT)
405 if (DT.TimeOfDay == TimeSpan.Zero)
408 Row[
Column.
ColumnId] = DT.ToShortDateString() +
", " + DT.ToLongTimeString();
426 this.UpdateGui(
new ThreadStart(() =>
431 return Task.CompletedTask;
438 this.elements.AddLast(
Event);
441 this.tables.Remove(
Event.TableId);
448 return Task.CompletedTask;
450 this.UpdateGui(
new ThreadStart(async () =>
462 return Task.CompletedTask;
469 this.elements.AddLast(
Event);
476 BitmapImage BitmapImage;
479 using (MemoryStream ms =
new MemoryStream(Bin))
481 BitmapImage =
new BitmapImage();
482 BitmapImage.BeginInit();
483 BitmapImage.CacheOption = BitmapCacheOption.OnLoad;
484 BitmapImage.StreamSource = ms;
485 BitmapImage.EndInit();
488 this.currentPanel.Children.Add(
new Image()
490 Source = BitmapImage,
491 Width = Pixels.
Width,
492 Height = Pixels.Height
497 string Xaml = await Markdown.GenerateXAML();
498 object Parsed = XamlReader.Parse(Xaml);
500 if (Parsed is UIElement Element)
501 this.currentPanel.Children.Add(Element);
504 this.currentPanel.Children.Add(
new TextBlock()
506 Text = Parsed?.ToString() ??
string.Empty,
507 Margin =
new Thickness(0, 0, 0, 6)
513 this.currentPanel.Children.Add(
new TextBlock()
516 Margin =
new Thickness(0, 0, 0, 6)
521 public void Dispose()
527 public void NewButton_Click(
object Sender, RoutedEventArgs e)
530 this.guiQueue.Clear();
531 this.elements.Clear();
534 this.currentPanel =
null;
536 this.ReportPanel.Children.Clear();
537 this.currentPanel = this.ReportPanel;
540 public void SaveButton_Click(
object Sender, RoutedEventArgs e)
542 this.SaveAsButton_Click(Sender, e);
545 public void SaveAsButton_Click(
object Sender, RoutedEventArgs e)
547 SaveFileDialog Dialog =
new SaveFileDialog()
550 CheckPathExists =
true,
551 CreatePrompt =
false,
553 Filter =
"XML Files (*.xml)|*.xml|HTML Files (*.html,*.htm)|*.html,*.htm|All Files (*.*)|*.*",
554 Title =
"Save report file"
557 bool? Result = Dialog.ShowDialog(
MainWindow.FindWindow(
this));
559 if (Result.HasValue && Result.Value)
563 if (Dialog.FilterIndex == 2)
565 StringBuilder Xml =
new StringBuilder();
571 string Html =
XSL.
Transform(Xml.ToString(), reportToHtml);
573 File.WriteAllText(Dialog.FileName, Html, Encoding.UTF8);
577 using (FileStream f = File.Create(Dialog.FileName))
588 MessageBox.Show(
MainWindow.FindWindow(
this), ex.Message,
"Unable to save file.", MessageBoxButton.OK, MessageBoxImage.Error);
593 private static readonly XslCompiledTransform reportToHtml =
XSL.
LoadTransform(
"Waher.Client.WPF.Transforms.ReportToHTML.xslt");
594 private static readonly XmlSchema schema =
XSL.
LoadSchema(
"Waher.Client.WPF.Schema.Report.xsd");
595 private const string reportNamespace =
"http://waher.se/Schema/Report.xsd";
596 private const string reportRoot =
"Report";
598 private void SaveAsXml(XmlWriter w)
600 w.WriteStartElement(reportRoot, reportNamespace);
601 w.WriteAttributeString(
"title", this.headerLabel.Text);
610 public void OpenButton_Click(
object Sender, RoutedEventArgs e)
614 OpenFileDialog Dialog =
new OpenFileDialog()
617 CheckFileExists =
true,
618 CheckPathExists =
true,
620 Filter =
"XML Files (*.xml)|*.xml|All Files (*.*)|*.*",
623 Title =
"Open report file"
626 bool? Result = Dialog.ShowDialog(
MainWindow.FindWindow(
this));
628 if (Result.HasValue && Result.Value)
630 XmlDocument Xml =
new XmlDocument()
632 PreserveWhitespace =
true
634 Xml.Load(Dialog.FileName);
636 this.Load(Xml, Dialog.FileName);
642 MessageBox.Show(ex.Message,
"Unable to load file.", MessageBoxButton.OK, MessageBoxImage.Error);
646 public async
void Load(XmlDocument Xml,
string FileName)
650 XSL.
Validate(FileName, Xml, reportRoot, reportNamespace, schema);
652 this.NewButton_Click(
null,
null);
653 this.headerLabel.Text =
XML.
Attribute(Xml.DocumentElement,
"title");
655 Dictionary<string, Column[]> ColumnsByTableId =
new Dictionary<string, Column[]>();
657 foreach (XmlNode N
in Xml.DocumentElement.ChildNodes)
659 if (!(N is XmlElement E))
Interaction logic for QueryResultView.xaml
void InitializeComponent()
InitializeComponent
Abstract base class for report elements.
abstract void ExportXml(XmlWriter Output)
Exports element to XML
Contains information about a report event.
Contains information about a report object.
static async Task< ReportObject > CreateAsync(XmlElement Xml)
Contains information about a report object.
Interaction logic for xaml
Represents a node in a concentrator.
Contains a markdown document. This markdown document class supports original markdown,...
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static XmlWriterSettings WriterSettings(bool Indent, bool OmitXmlDeclaration)
Gets an XML writer settings object.
Static class managing loading of XSL resources stored as embedded resources or in content files.
static XmlSchema LoadSchema(string ResourceName)
Loads an XML schema from an embedded resource.
static XslCompiledTransform LoadTransform(string ResourceName)
Loads an XSL transformation from an embedded resource.
static string Transform(string XML, XslCompiledTransform Transform)
Transforms an XML document using an XSL transform.
static void Validate(string ObjectID, XmlDocument Xml, params XmlSchema[] Schemas)
Validates an XML document given a set of XML schemas.
Class representing an event.
string Object
Object related to the event.
Static class managing the application event log. Applications and services log events on this static ...
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.
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Event arguments for node query events.
Event arguments for node query section events.
QueryEventType EventType
Event type
string EventMessage
Event Message
QueryEventLevel EventLevel
Event level
Event arguments for node query object events.
Event arguments for node query section events.
QuerySection Section
Section
Event arguments for node query section events.
string StatusMessage
Status Message
Event arguments for node query table events.
Event arguments for node query table events.
Record[] NewRecords
New Records
Client-side Node Query object. It collects the results of the query.
async Task ResumeAsync()
Resumes a paused query reception.
string Title
Title os response report.
void Dispose()
IDisposable.Dispose
byte[] Binary
Binary representation of object.
string ContentType
Content-Type
string Header
Section Header
Table TableDefinition
Table definitions.
Defines a column in a table.
string Header
Optional localized header.
byte? NrDecimals
Optional Number of Decimals.
Class handling the reception of data from a query.
Defines a record in a table.
object[] Elements
Record elements.
Represents a table in a query result.
Interface for tab view user controls in the client.
QueryEventType
Query event type.