public HexAdornmentLayerElementImpl(VSTE.AdornmentPositioningBehavior behavior, HexBufferSpan?visualSpan, object tag, UIElement adornment, VSTE.AdornmentRemovedCallback removedCallback)
 {
     Adornment       = adornment;
     Behavior        = behavior;
     RemovedCallback = removedCallback;
     Tag             = tag;
     VisualSpan      = visualSpan;
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="adornment">Adornment element</param>
 /// <param name="removalCallback">Called when the adornment is removed, may be null</param>
 /// <param name="topSpace">Top space or null to use the default value</param>
 /// <param name="baseline">Base line or null to use the default value</param>
 /// <param name="textHeight">Text height or null to use the default value</param>
 /// <param name="bottomSpace">Bottom space or null to use the default value</param>
 /// <param name="affinity">Position affinity or null to use the default value</param>
 public HexIntraTextAdornmentTag(UIElement adornment, VSTE.AdornmentRemovedCallback removalCallback, double?topSpace, double?baseline, double?textHeight, double?bottomSpace, VST.PositionAffinity?affinity)
 {
     Adornment       = adornment ?? throw new ArgumentNullException(nameof(adornment));
     RemovalCallback = removalCallback;
     TopSpace        = topSpace;
     Baseline        = baseline;
     TextHeight      = textHeight;
     BottomSpace     = bottomSpace;
     Affinity        = affinity;
 }
        bool AddAdornment(AdornmentTagInfo adornmentInfo, HexViewLine line)
        {
            SizeChangedEventHandler sizeChanged = (a, e) => {
                var bounds = line.GetAdornmentBounds(adornmentInfo);
                if (bounds == null)
                {
                    return;
                }
                // Sometimes the size just gets changed very little, eg. from 400 to 399.95.....
                const double d = 0.5;
                if (e.NewSize.Height <= bounds.Value.Height + d && e.NewSize.Width <= bounds.Value.Width + d)
                {
                    return;
                }
                tagger?.RefreshSpans(new HexBufferSpanEventArgs(adornmentInfo.BufferSpan));
            };

            adornmentInfo.TopUIElement.SizeChanged += sizeChanged;

            VSTE.AdornmentRemovedCallback removedCallback = (a, b) => {
                adornmentTagInfos.Remove(adornmentInfo);
                adornmentInfo.TopUIElement.SizeChanged -= sizeChanged;
                adornmentInfo.TopUIElement.OnRemoved();
                if (adornmentInfo.HexTagSpan != null)
                {
                    adornmentInfo.HexTagSpan.Tag.RemovalCallback?.Invoke(adornmentInfo.HexTagSpan, b);
                }
                else
                {
                    adornmentInfo.HexTextTagSpan.Tag.RemovalCallback?.Invoke(adornmentInfo.HexTextTagSpan, b);
                }
            };

            Debug.Assert(!adornmentTagInfos.Contains(adornmentInfo));
            adornmentTagInfos.Add(adornmentInfo);
            // Use OwnerControlled because there are corner cases that the adornment layer can't handle,
            // eg. an adornment with buffer span length == 0 that is shown on its own line (word wrap).
            bool added = layer.AddAdornment(VSTE.AdornmentPositioningBehavior.OwnerControlled, (HexBufferSpan?)null, adornmentInfo, adornmentInfo.TopUIElement, removedCallback);

            if (!added)
            {
                removedCallback(null, adornmentInfo.TopUIElement);
            }
            return(added);
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="adornment">Adornment element</param>
 /// <param name="removalCallback">Called when the adornment is removed, may be null</param>
 public HexIntraTextAdornmentTag(UIElement adornment, VSTE.AdornmentRemovedCallback removalCallback)
     : this(adornment, removalCallback, null, null, null, null, null)
 {
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="adornment">Adornment element</param>
 /// <param name="removalCallback">Called when the adornment is removed, may be null</param>
 /// <param name="affinity">Position affinity or null to use the default value</param>
 public HexIntraTextAdornmentTag(UIElement adornment, VSTE.AdornmentRemovedCallback removalCallback, VST.PositionAffinity?affinity)
     : this(adornment, removalCallback, null, null, null, null, affinity)
 {
 }
 /// <summary>
 /// Adds an adornment. Returns true if the adornment was added.
 /// </summary>
 /// <param name="behavior">Positioning behavior</param>
 /// <param name="line">Line</param>
 /// <param name="tag">Tag</param>
 /// <param name="adornment">Adornment</param>
 /// <param name="removedCallback">Called when the adornment is removed</param>
 /// <returns></returns>
 public bool AddAdornment(VSTE.AdornmentPositioningBehavior behavior, HexBufferLine line, object tag, UIElement adornment, VSTE.AdornmentRemovedCallback removedCallback)
 {
     if (line == null)
     {
         throw new ArgumentNullException(nameof(line));
     }
     return(AddAdornment(behavior, line.BufferSpan, tag, adornment, removedCallback));
 }
 /// <summary>
 /// Adds an adornment. Returns true if the adornment was added.
 /// </summary>
 /// <param name="behavior">Positioning behavior</param>
 /// <param name="visualSpan">Span</param>
 /// <param name="tag">Tag</param>
 /// <param name="adornment">Adornment</param>
 /// <param name="removedCallback">Called when the adornment is removed</param>
 /// <returns></returns>
 public abstract bool AddAdornment(VSTE.AdornmentPositioningBehavior behavior, HexBufferSpan?visualSpan, object tag, UIElement adornment, VSTE.AdornmentRemovedCallback removedCallback);
        public override bool AddAdornment(VSTE.AdornmentPositioningBehavior behavior, HexBufferSpan?visualSpan, object tag, UIElement adornment, VSTE.AdornmentRemovedCallback removedCallback)
        {
            if (adornment == null)
            {
                throw new ArgumentNullException(nameof(adornment));
            }
            if (visualSpan != null && visualSpan.Value.IsDefault)
            {
                throw new ArgumentException();
            }
            if (visualSpan == null && behavior == VSTE.AdornmentPositioningBehavior.TextRelative)
            {
                throw new ArgumentNullException(nameof(visualSpan));
            }
            if ((uint)behavior > (uint)VSTE.AdornmentPositioningBehavior.TextRelative)
            {
                throw new ArgumentOutOfRangeException(nameof(behavior));
            }
            if (layerKind != HexLayerKind.Normal)
            {
                if (behavior != VSTE.AdornmentPositioningBehavior.OwnerControlled)
                {
                    throw new ArgumentOutOfRangeException(nameof(behavior), "Special layers must use AdornmentPositioningBehavior.OwnerControlled");
                }
                if (visualSpan != null)
                {
                    throw new ArgumentOutOfRangeException(nameof(visualSpan), "Special layers must use a null visual span");
                }
            }
            bool canAdd = visualSpan == null || HexView.HexViewLines.IntersectsBufferSpan(visualSpan.Value);

            if (canAdd)
            {
                var layerElem = new HexAdornmentLayerElementImpl(behavior, visualSpan, tag, adornment, removedCallback);
                canvas.Children.Add(layerElem.Adornment);
                adornmentLayerElements.Add(layerElem);
            }
            return(canAdd);
        }