private void ShowDownloadedImage(ITextViewLine line, SnapshotSpan span, Color bgColor, MyImage image)
        {
            if (bgColor.A != 0 && image.BgColor != bgColor)
            {
                image.Scale   = 1;
                image.Source  = image.ReplaceTransparency(image.Source, bgColor);
                image.BgColor = bgColor;
            }

            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);
            }
        }
示例#2
0
        /// <summary>
        /// On layout change add the adornment to any reformatted lines
        /// </summary>
        private void LayoutChangedHandler(object sender, TextViewLayoutChangedEventArgs e)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (!Enabled)
            {
                return;
            }

            _errorTags.Clear();
            if (TagsChanged != null)
            {
                TagsChanged(this, new SnapshotSpanEventArgs(new SnapshotSpan(_view.TextSnapshot, new Span(0, _view.TextSnapshot.Length))));
            }

            OnTagsChanged(new SnapshotSpan(_view.TextSnapshot, new Span(0, _view.TextSnapshot.Length)));

            foreach (ITextViewLine line in _view.TextViewLines) // TODO [?]: implement more sensible handling of removing error tags, then use e.NewOrReformattedLines
            {
                int lineNumber = line.Snapshot.GetLineFromPosition(line.Start.Position).LineNumber;
                //TODO [?]: Limit rate of calls to the below when user is editing a line
                try
                {
                    CreateVisuals(line, lineNumber);
                }
                catch (InvalidOperationException ex)
                {
                    ExceptionHandler.Notify(ex, true);
                }
            }

            // Sometimes, on loading a file in an editor view, the line transform gets triggered before the image adornments
            // have been added, so the lines don't resize to the image height. So here's a workaround:
            // Changing the zoom level triggers the required update.
            // Need to do it twice - once to trigger the event, and again to change it back to the user's expected level.
            if (!_initialised1)
            {
                _view.ZoomLevel++;
                _initialised1 = true;
            }
            if (!_initialised2)
            {
                _view.ZoomLevel--;
                _initialised2 = true;
            }
        }
示例#3
0
        /// <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, string absFilename)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var directory = absFilename != null?System.IO.Path.GetDirectoryName(absFilename) : null;

            var lineText   = line.Extent.GetText().Split(new[] { "\r\n", "\r" }, StringSplitOptions.None)[0];
            var matchIndex = ImageCommentParser.Match(_contentTypeName, lineText, out var matchedText);

            if (matchIndex >= 0)
            {
                //lineText = line.Extent.GetText().Split(new string[] { "\r\n", "\r" }, StringSplitOptions.None)[0];
                // Get coordinates of text
                var start = line.Extent.Start.Position + matchIndex;
                var end   = line.Start + (line.Extent.Length - 1);
                var span  = new SnapshotSpan(_view.TextSnapshot, Span.FromBounds(start, end));

                ImageCommentParser.TryParse(matchedText, out var parsedImgData, out var parsingError);

                if (parsingError != null)
                {
                    if (Images.ContainsKey(lineNumber))
                    {
                        _layer.RemoveAdornment(Images[lineNumber]);
                        Images.Remove(lineNumber);
                    }

                    _errorTags.Add(new TagSpan <ErrorTag>(span,
                                                          new ErrorTag("XML parse error", $"Problem with comment format: {parsingError}")));

                    return;
                }

                string loadingMessage = null;

                // Check for and update existing image
                CommentImage image = Images.ContainsKey(lineNumber) ? Images[lineNumber] : null;
                if (image != null)
                {
                    if (!image.Attributes.IsEqual(parsedImgData))
                    {
                        image.TrySet(directory, parsedImgData, out loadingMessage, () => CreateVisuals(line, lineNumber, absFilename));
                    }
                }
                else // No existing image, so create new one
                {
                    image = new CommentImage(_variableExpander);
                    image.TrySet(directory, parsedImgData, out loadingMessage, () => CreateVisuals(line, lineNumber, absFilename));
                    Images.Add(lineNumber, image);
                }

                // Position image and add as adornment
                if (loadingMessage == null && image.Source != null)
                {
                    var geometry = _view.TextViewLines.GetMarkerGeometry(span);
                    if (geometry == 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?");
                    }
                    var textLeft   = geometry.Bounds.Left;
                    var 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, loadingMessage == null ?
                                                          new ErrorTag("No image set", "No image set") :
                                                          new ErrorTag("Trouble loading image", loadingMessage)));
                }
            }
            else
            {
                if (Images.ContainsKey(lineNumber))
                {
                    Images.Remove(lineNumber);
                }
            }
        }
        /// <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 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;
                string    imageUrl;
                double    scale;
                Color     bgColor = new Color();
                ImageCommentParser.TryParse(matchedText, out imageUrl, out scale, ref bgColor, 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;
                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.BgColor != bgColor) // URL different, so set new source
                    {
                        existingImage.TrySet(imageUrl, scale, bgColor, out imageLoadingException, () => CreateVisuals(line, lineNumber));
                    }
                    else if (existingImage.Url == imageUrl && Math.Abs(existingImage.Scale - scale) > 0.0001)   // URL same but scale changed
                    {
                        existingImage.Scale = scale;
                    }
                }
                else // No existing image, so create new one
                {
                    image = new MyImage(_variableExpander);
                    image.TrySet(imageUrl, scale, bgColor, out imageLoadingException, () => CreateVisuals(line, lineNumber));
                    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);
                }
            }
        }
        /// <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 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;
                string    imageUrl;
                double    scale;
                Color     bgColor = new Color();
                ImageCommentParser.TryParse(matchedText, out imageUrl, out scale, ref bgColor, 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;
                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) // URL different, so set new source
                    {
                        existingImage.TrySet(imageUrl, scale, bgColor, out imageLoadingException, () => CreateVisuals(line, lineNumber));
                        if (image.BgColor != null)
                        {
                            image.BgColor.R = 254;
                        }
                    }
                }
                else // No existing image, so create new one
                {
                    image = new MyImage(_variableExpander);
                    image.TrySet(imageUrl, scale, bgColor, out imageLoadingException, () => CreateVisuals(line, lineNumber));
                    if (image.BgColor != null)
                    {
                        image.BgColor.R = 254;
                    }

                    Images.Add(lineNumber, image);
                }

                // Position image and add as adornment
                if (imageLoadingException == null)
                {
                    try
                    {
                        _layer.RemoveAdornment(image);
                    }
                    catch (Exception ex)
                    {
                        // No expected exceptions, so tell user something is wrong.
                        ExceptionHandler.Notify(ex, true);
                    }

                    if ((image.Source as BitmapFrame)?.IsDownloading ?? false)
                    {
                        (image.Source as BitmapFrame).DownloadCompleted += (x, y) =>
                        {
                            if (x == image.Source)
                            {
                                ShowDownloadedImage(line, span, bgColor, image);
                            }
                        };
                    }
                    else
                    {
                        ShowDownloadedImage(line, span, bgColor, image);
                    }
                }
                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);
                }
            }
        }