private void WriteToFieldLog(string source, TraceEventType eventType, int id, string msg)
        {
            string shortMsg = null;

            // Name comparisons roughly in a descending order of frequency, to optimise performance
            if (source == PresentationTraceSources.DataBindingSource.Name)
            {
                HandleDataBindingMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.RoutedEventSource.Name)
            {
                if (id == 3)
                {
                    if (eventType == TraceEventType.Start)
                    {
                        eventType = TraceEventType.Verbose;                           // Don't indent for this
                    }
                    else if (eventType == TraceEventType.Stop)
                    {
                        return;                           // Don't log this
                    }
                }
                //if (id == 4)
                //{
                //    return;   // Don't log this
                //}
                HandleRoutedEventMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.ResourceDictionarySource.Name)
            {
                HandleResourceDictionaryMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.MarkupSource.Name)
            {
                HandleMarkupMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.AnimationSource.Name)
            {
                HandleAnimationMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.DependencyPropertySource.Name)
            {
                HandleDependencyPropertyMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.FreezableSource.Name)
            {
                if (id == 1)
                {
                    return;                       // Don't log this, it appears everywhere and comes from bugs in WPF
                }
                HandleFreezableMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.HwndHostSource.Name)
            {
                HandleHwndHostMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.NameScopeSource.Name)
            {
                HandleNameScopeMessage(id, ref msg, ref shortMsg);
            }
            else if (source == PresentationTraceSources.ShellSource.Name)
            {
                HandleShellMessage(id, ref msg, ref shortMsg);
            }
            // DocumentsSource does not have any information and is not augmented here

            // Fallback short message if unknown event ID
            if (shortMsg == null)
            {
                shortMsg = "ID " + id;
            }

            // Select appropriate FieldLog priority or otherwise highlight event type
            FieldLogPriority prio = FieldLogPriority.Trace;

            switch (eventType)
            {
            case TraceEventType.Critical:
            case TraceEventType.Error:
                prio = FieldLogPriority.Error;
                break;

            case TraceEventType.Warning:
                prio = FieldLogPriority.Warning;
                break;

            case TraceEventType.Information:
                prio = FieldLogPriority.Info;
                break;

            case TraceEventType.Start:
                //shortMsg += " [Start]";
                break;

            case TraceEventType.Stop:
                shortMsg += " [Stop]";
                break;

            case TraceEventType.Suspend:
                shortMsg += " [Suspend]";
                break;

            case TraceEventType.Resume:
                shortMsg += " [Resume]";
                break;

            case TraceEventType.Transfer:
                shortMsg += " [Transfer]";
                break;
            }

            // Write message to the log if it's still there
            if (!FL.IsShutdown)
            {
                if (eventType == TraceEventType.Stop)
                {
                    indentLevel--;
                }

                string indentPrefix = null;
                if (indentLevel < 0)
                {
                    indentPrefix = "«";
                    indentLevel  = 0;
                }
                else if (indentLevel > 0)
                {
                    // Use a cached pre-generated indent prefix for better performance
                    while (indentStrings.Count <= indentLevel)
                    {
                        int    newLevel = indentStrings.Count;
                        string prefix   = "";
                        for (int i = 1; i <= newLevel; i++)
                        {
                            prefix += "-  ";
                        }
                        indentStrings.Add(prefix);
                    }
                    indentPrefix = indentStrings[indentLevel];
                }

                FL.Text(
                    prio,
                    indentPrefix + shortName + ": " + shortMsg,
                    (!string.IsNullOrEmpty(msg) ? msg + "\n\n" : "") +
                    "Event ID: " + id + "\nEvent type: " + eventType + "\nSource: " + sourceName);

                if (eventType == TraceEventType.Start)
                {
                    indentLevel++;
                }
            }
        }