/// <summary> /// Scans text line for matching image comment signature, then adds new or updates existing image adornment /// </summary> private void CreateVisuals(ITextViewLine line, int lineNumber) { #pragma warning disable 219 bool imageDetected = false; // useful for tracing #pragma warning restore 219 string lineText = line.Extent.GetText(); string imageUrl; double scale; string matchedText; int matchIndex = ImageCommentParser.Match(_contentTypeName, lineText, out matchedText); if (matchIndex >= 0) { // Get coordinates of text int start = line.Extent.Start.Position + matchIndex; int end = line.Start + (line.Extent.Length - 1); var span = new SnapshotSpan(_view.TextSnapshot, Span.FromBounds(start, end)); Exception xmlParseException; ImageCommentParser.TryParse(matchedText, out imageUrl, out scale, out xmlParseException); if (xmlParseException != null) { if (Images.ContainsKey(lineNumber)) { _layer.RemoveAdornment(Images[lineNumber]); Images.Remove(lineNumber); } _errorTags.Add(new TagSpan <ErrorTag>(span, new ErrorTag("XML parse error", getErrorMessage(xmlParseException)))); return; } MyImage image = null; Exception imageLoadingException = null; // Check for and update existing image MyImage existingImage = Images.ContainsKey(lineNumber) ? Images[lineNumber] : null; if (existingImage != null) { image = existingImage; if (existingImage.Url == imageUrl && existingImage.Scale != scale) // URL same but scale changed { existingImage.Scale = scale; } else if (existingImage.Url != imageUrl) // URL different, so set new source { existingImage.TrySet(imageUrl, scale, out imageLoadingException); } } else // No existing image, so create new one { image = new MyImage(_variableExpander); image.TrySet(imageUrl, scale, out imageLoadingException); Images.Add(lineNumber, image); } // Position image and add as adornment if (imageLoadingException == null) { Geometry g = _view.TextViewLines.GetMarkerGeometry(span); if (g == null) // Exceptional case when image dimensions are massive (e.g. specifying very large scale factor) { throw new InvalidOperationException("Couldn't get source code line geometry. Is the loaded image massive?"); } double textLeft = g.Bounds.Left; double textBottom = line.TextBottom; Canvas.SetLeft(image, textLeft); Canvas.SetTop(image, textBottom); // Add image to editor view try { _layer.RemoveAdornment(image); _layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, line.Extent, null, image, null); } catch (Exception ex) { // No expected exceptions, so tell user something is wrong. ExceptionHandler.Notify(ex, true); } } else { if (Images.ContainsKey(lineNumber)) { Images.Remove(lineNumber); } _errorTags.Add(new TagSpan <ErrorTag>(span, new ErrorTag("Trouble loading image", getErrorMessage(imageLoadingException)))); } imageDetected = true; } else { if (Images.ContainsKey(lineNumber)) { Images.Remove(lineNumber); } } }