Background image

SyntaxEditor for WPF Forum

Posted 5 years ago by Dirk Zellerfeld
Version: 19.1.0681
Avatar

How can I have a background image in the editor? Since there is no built-in support I thought I could simply add an adornment following the watermark example in the demo application but with an image instead of a textbox. Works pretty well but unfortunately it doesn't if the image is too big / small. It's never properly stretched the way that it fills the screen while respecting the aspect ratio.

This is my modified code:

private void OnViewTextAreaLayout(object sender, TextViewTextAreaLayoutEventArgs e)
{
    // Get the horizontal scroll
    double firstVisibleX = (e.View is IEditorView view ? view.ScrollState.HorizontalAmount : 0.0);

    // Determine the center of the text area viewport
    Rect textAreaViewportBounds = e.View.TextAreaViewportBounds;
    Point center = new Point(firstVisibleX + textAreaViewportBounds.Width / 2 / e.View.SyntaxEditor.ZoomLevelAnimated, textAreaViewportBounds.Height / 2 / e.View.SyntaxEditor.ZoomLevelAnimated);

    // Determine the center of the watermark element
    UIElement element = watermarkAdornment.VisualElement;
    if (!(element is Image image))
        return;
    Point textBlockCenter = new Point(image.Source.Width / 2, image.Source.Height / 2);

    // Adjust scale
    var scaleTrans = (ScaleTransform)image.RenderTransform;
    scaleTrans.ScaleX = 1 / e.View.SyntaxEditor.ZoomLevelAnimated;
    scaleTrans.ScaleY = 1 / e.View.SyntaxEditor.ZoomLevelAnimated;

    // Determine the watermark location
    Point watermarkLocation = new Point(center.X - textBlockCenter.X, center.Y - textBlockCenter.Y);

    // Set the watermark location
    watermarkAdornment.Location = watermarkLocation;
}
private IAdornment CreateWatermarkAdornment()
{
    Image image = new Image()
    {
        Source = new BitmapImage(new Uri("C:\\test.jpg")),
        IsHitTestVisible = false,
        Stretch = Stretch.UniformToFill,
        RenderTransform = new ScaleTransform(),
        RenderTransformOrigin = new Point(0.5, 0.5)
    };
    // Add the UIElement to the adornment layer as an adornment
    return this.AdornmentLayer.AddAdornment(AdornmentChangeReason.Other, image, new Point(), null, null);
}

Comments (6)

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Dirk,

Think of adornment layers like canvas controls in general.  It's not going to auto-size the controls in the adornment layers, so you must set the Image.Width and Height appropriately within OnViewTextAreaLayout.  You could probably set it to be the textAreaViewportBounds.Size and set the Location to (0, 0).


Actipro Software Support

Posted 5 years ago by Dirk Zellerfeld
Avatar

Thanks, this is what I've got so far which works fine. But the image goes bigger (and out of area) when zooming into via CTRL+mouse wheel. Is there a way to disable the zoom for the adornment only or make it keep the same size?

Another thing I've noticed that when setting the opacity to something like 0.4, the text hardly gets readable. It looks like as if the text in the script editor also has reduced opacity. I have to set it to a maximum of 0.2 to maintain readability.

private void OnViewTextAreaLayout(object sender, TextViewTextAreaLayoutEventArgs e)
{
    // Determine the center of the text area viewport
    Rect textAreaViewportBounds = e.View.TextAreaViewportBounds;

    // Determine the center of the watermark element
    UIElement element = watermarkAdornment.VisualElement;
    if (!(element is Image image))
        return;

    var scale = e.View.SyntaxEditor.ZoomLevel / 1;
    if (scale == 1)
        image.LayoutTransform = Transform.Identity;
    else
    {
        var scaleTransform = new ScaleTransform(scale, scale);
        scaleTransform.Freeze();
        image.LayoutTransform = scaleTransform;
    }

    Size size;
    image.ClearValue(FrameworkElement.HeightProperty);
    image.ClearValue(FrameworkElement.WidthProperty);

	image.Measure(new Size(textAreaViewportBounds.Width, textAreaViewportBounds.Height));
	size = image.DesiredSize;
	image.Width = size.Width;
	image.Height = size.Height;
	
	watermarkAdornment.Location = new Point(0, 0);
}

private IAdornment? CreateWatermarkAdornment()
{
    Image image = new Image()
    {
        Source = new BitmapImage(new Uri("C:\\test.jpg")),
        IsHitTestVisible = false,
        Opacity = 0.2
    };
    // Add the UIElement to the adornment layer as an adornment
    return this.AdornmentLayer.AddAdornment(AdornmentChangeReason.Other, image, new Point(), null, null);
}
Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Dirk,

I'm not sure how a LayoutTransform would affect the image rendering here.  I see you are trying to compensate for the zoom level.  You probably want to use the ZoomLevelAnimated property instead of ZoomLevel since the animated version is real-time.  And perhaps instead of using LayoutTransform at all, you simply adjust the width and height of the image by the scale factor.  As long as it can stretch, it should support remaining relatively constant as zooming occurs.  There isn't an option to ignore zoom for adornments.

As for text, I don't believe any of our default foreground text colors are semi-transparent.


Actipro Software Support

Posted 5 years ago by Dirk Zellerfeld
Avatar

I've removed the layouttransform part, seems to work also without it. Still couldn't get it to stay at its size when zooming, even when I set stretch to uniform for the image. Also the text issue kinda bugs me. When I place an image with opacity 0.5 on a normal window and put a textblock on top of it it's more readable then the text on the script editor.

Ah well... perhaps we get an official background image support in the future. Just got it to it when trying the new MS Terminal, thought something like that is a neat feature for the script editor :)

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Dirk,

What happens if you set the attached TextOptions.TextFormattingMode property to Ideal on the editor control.  Does that make any difference with the text readability?

We can make a note of the background image feature request.  Would you want it to scale uniformly to fill the text area bounds thereby potentially clipping left/right or top/bottom as needed?


Actipro Software Support

Posted 5 years ago by Dirk Zellerfeld
Avatar

I think the best would be to have the image act like UniformToFill to make sure it always fills the text area bounds but also respect the aspectio rate. This allows all images to be used as background and can easily be adjusted to behave correctly. In MS Terminal preview the user can define how and whether the image is streched but this customizability might be out of scope unless you want to go for the extra work.

I've set TextOptions.TextFormattingMode to ideal but it doesn't change anything. I think it's rather the foreground color of the script editor which makes it less readable. I'm using metro dark and for the textblock I've used white but the editor seems to be a little bit less bright.

The latest build of this product (v24.1.1) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.