/////////////////////////////////////////////////////////////////////////////////////////////////////
        // NON-PUBLIC PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Examines the cached elements, prunes ones that no longer have valid tags, and returns a match if found.
        /// </summary>
        /// <param name="tag">The target tag for which to search.</param>
        /// <returns>A cached element, if found.</returns>
        private AdornmentElement GetCachedElement(object tag)
        {
            AdornmentElement targetElement = null;

            if (tag != null)
            {
                for (var index = cachedElements.Count - 1; index >= 0; index--)
                {
                    var tagRef = cachedElements[index].Item1;
                    if (tagRef.IsAlive)
                    {
                        // If there is a tag match, use the cached element and remove the entry
                        if (tagRef.Target == tag)
                        {
                            targetElement = cachedElements[index].Item2;
                            cachedElements.RemoveAt(index);
                        }
                    }
                    else
                    {
                        // Remove the entry
                        cachedElements.RemoveAt(index);
                    }
                }
            }

            return(targetElement);
        }
        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // PUBLIC PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Adds an adornment to the <see cref="AdornmentLayer"/>.
        /// </summary>
        /// <param name="viewLine">The current <see cref="ITextViewLine"/> being examined.</param>
        /// <param name="tagRange">The <see cref="ITag"/> and the range it covers.</param>
        protected override void AddAdornment(ITextViewLine viewLine, TagSnapshotRange <IntraLineViewportTag> tagRange)
        {
            // Determine the bounds
            var bounds     = this.GetAdornmentBounds(tagRange.Tag);
            var charBounds = viewLine.GetCharacterBounds(tagRange.SnapshotRange.StartOffset);

            bounds.Y = charBounds.Bottom;

            // See if a cached version of the element for the tag is available
            var element = this.GetCachedElement(tagRange.Tag);

            if (element == null)
            {
                // Create the element
                element = new AdornmentElement();
            }

            // Update the size
            element.Width  = bounds.Width;
            element.Height = bounds.Height;
            element.Tag    = tagRange.Tag;

            // Add the adornment
            this.AdornmentLayer.AddAdornment(AdornmentChangeReason.Other, element, bounds.Location, tagRange.Tag.Key, OnAdornmentRemoved);
        }