I want to show the user a summary of all the relevant messages that have occurred during a code execution (e.g. parsing, algorithm, conversion, validation etc). The messages should be showed together when the process is done.
A similar incident might occur none, one or several times. The user should be notified if the incident occurred. There might be several types of incidents.
I'm not sure if the scenario is clear, but maybe some code will help:
PSEUDO-CODE:
begin
//Execute computing process//
repeat
Set a flag if an incident occurs
Set another flag if another incident occurs
until done
//Show message to user//
if AnyFlagIsSet then
ShowPrettyMessageToUser
end;
EXECUTABLE DELPHI CODE:
program Test;
{$APPTYPE CONSOLE}
uses
SysUtils, StrUtils;
var
i: Integer;
tmpFlags: Array[1..4] of Boolean;
tmpMessage: String;
tmpChar: Char;
begin
Randomize;
repeat
//Initialization//
for i := 1 to 4 do
tmpFlags[i] := False;
//Will insident occur?//
for i := 0 to 5 do
begin
if (Random(10) = 0) then tmpFlags[1] := True;
if (Random(10) = 0) then tmpFlags[2] := True;
if (Random(10) = 0) then tmpFlags[3] := True;
if (Random(10) = 0) then tmpFlags[4] := True;
end;
//Show message//
tmpMessage := '';
if tmpFlags[1] then tmpMessage := tmpMessage + IfThen(tmpMessage <> '', #13#10+#13#10) + 'Incident 1';
if tmpFlags[2] then tmpMessage := tmpMessage + IfThen(tmpMessage <> '', #13#10+#13#10) + 'Incident 2';
if tmpFlags[3] then tmpMessage := tmpMessage + IfThen(tmpMessage <> '', #13#10+#13#10) + 'Incident 3';
if tmpFlags[4] then tmpMessage := tmpMessage + IfThen(tmpMessage <> '', #13#10+#13#10) + 'Incident 4';
Writeln('----------');
Writeln(tmpMessage);
Writeln('----------');
Writeln;
Write('Again? (Y/N) ');
Readln(tmpChar);
until tmpChar <> 'y';
end.
The code in the iteration is quiet complex in real life, of course. And the messages are also more informative, and may even be formatted and multi-lined.
So...
Is there a best practice or pattern that can be used for this?
Any Delphi-component that handles this?
An easy solution would be to use a TStringList
to collect all messages. You can then either display the strings in a listbox or concatenate the strings (in this case all messages should be valid sentences).
Pseudocode:
procedure DoSomething(Log : TStrings);
begin
//...
Log.Add ('Some hint.');
//...
Log.Add ('Some error happened.');
//...
end;
DoSomething (Log);
if (Log.Count > 0) then
LogListBox.Items.AddStrings (Log);
For formatted or multi-lined messages you could store HTML strings in the stringlist and use a component that can display HTML formatted text to display the messages.
Edit: If you want no duplicate messages, just do
Log.Duplicates := dupIgnore;
I would (where the memory requirements are not a factor) create a class which uses a hashed stringlist as a catalog, where X number of "logitems" could be inserted as objects. This allows some control over how the items are grouped. By accessing the stringlist using a normal index - you get a linear timeline. But accessing the items through it's hash-keys, you get the items grouped by content. Using a hashed stringlist is much faster to work with since it employes a lookup-table.
For an overall, application-wide solution, I have used the midas library's TClientDataset which has been with Delphi for ages. Just remember to declare "midaslib" as the first unit in your project and it's linked directly into your binary (no need to ship midaslib.dll). This gives you the benefit of fields and sorting by message/error types. As long as the record count dont get above 10k it's both fast and stable to work with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With