Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Horizontal scrollbar resizing while scrolling vertically #282

Open
sonofachuck opened this issue May 12, 2021 · 10 comments
Open

Horizontal scrollbar resizing while scrolling vertically #282

sonofachuck opened this issue May 12, 2021 · 10 comments

Comments

@sonofachuck
Copy link

Currently, when scrolling a document that has varying line lengths, only the currently visible lines are used to determine the horizontal scroll width. Preferably what should happen, and what happens in pretty much all other text viewers, is that the document's largest horizontal width is found and then that value is used regardless of the lengths of the currently visible lines. This is with text-wrap turned off.

Fixing this would prevent the horizontal scroll thumb from constantly moving around and resizing, as well as keeping the vertical thumb from jumping up and down if the horizontal scrollbar happens to appear and disappear during scrolling.

If there is some existing method of preventing this, I couldn't find it in the documentation (which is quite thorough and helpful, btw). I did try putting the editor inside another scrollviewer, which fixed the horiz extent issue, but introduced worse issues for documents that have many lines in them, such as rendering very slowly, etc.

@futuremotiondev
Copy link

I am running into this issue and wondering if you found a solution or a resolution.

If I can't get the horizontal scrollbar from jumping around due to varying content width, I'll need to use a different component from someone else. I really want to stick with AvalonEdit, though.

@sonofachuck
Copy link
Author

The only solution would be to go into the source and rewrite some parts, which I've never delved into. It's baffling that this was marked as "Issue-Enhancement", and then forgotten about, when it's clearly a bug.

@jimfoye
Copy link
Contributor

jimfoye commented Aug 3, 2022

I've honestly never seen this as a problem. In my case, I have to support some big files, so the existing approach might actually be better from a performance standpoint.

@siegfriedpammer
Copy link
Member

Yes, I would argue that this is not a bug at all, but rather by-design, as we calculate the required scrollbar size from the currently visible lines of text.

@sonofachuck
Copy link
Author

Being in by design would be alright if it added some worthwhile feature, but, instead, it's actually unhelpful. Take a look at Visual Studio, WordPad, Notepad, MS Word, Notepad++, etc, etc. None of them work this way because you want to preserve the horizontal and vertical scroll position that the user has chosen, regardless of them scrolling to a different section of a document that may have shorter lines.

@futuremotiondev
Copy link

To add on to what @sonofachuck is saying:

  1. VS Code, Visual Studio, Sublime, all JetBrains products, Notepad++, Eclipse, and any other Code editor that I've ever interacted with all calculate horizontal scroll based on the longest line in the document. This behavior provides important visual feedback when you look at the horizontal scrollbar so you know exactly how much your code as a whole extends in the horizontal direction and you can intuit the overall structure of your document much more easily.

  2. One terrible side effect of your current implementation is that the horizontal scrollbar keeps jumping around erratically as you scroll the document vertically. This is especially noticeable if the TextEditor is smaller and the file you're editing has a mixture of very long lines and very short lines.

I come from a design/UX background (I make my primary living from interface design and UI/UX), and consistency is extremely important when it comes to UI implementation. The current scrolling behavior is just for lack of a better word... weird. It doesn't at all make sense if you're editing normal code. People will not expect this behavior, period. And that is full-stop "bad".

(I want to know how wide my document is! And where the offending lines exist).

  1. Your current implementation may have performance benefits and make sense for editors that have a feature to read "very large files", but is not suitable at all as a default behavior and breaks best practices. I would propose your current implementation would be a nice option as a toggle-able feature (Large file support) because you're only processing a limited amount of data at a time and you can probably handle files that would choke a normal text editor. However, as a default behavior, it makes absolutely no sense at all and flies in the face of established and time-tested patterns.

Yes, I would argue that this is not a bug at all, but rather by-design, as we calculate the required scrollbar size from the currently visible lines of text.

Yes, we know how you calculate required scrollbar size. We know it's "by design". This doesn't mean it isn't a poor design choice.

I don't have a lot of hope at this point, but I would propose you sideline the current behavior as toggleable ("Large File Support"), and implement a new default that just measures horizontal scroll distance by the longest line in the document... like literally every other code/text editor in existence.

Nobody wants to see their horizontal scrollbar dancing around at the bottom of the window erratically as it provides no reliable insight into the full structure of your document and essentially reduces usability.

Ultimately, if you want to die on your "It's not a bug, it's a feature!" hill, nobody can stop you. But I believe AvalonEdit can be one of the best (if not the best) C# WPF code editing solutions/components in existence. This critique comes from a place of love, believe it or not. It's lightweight, fast, and handles everything else reliably. It's really easy to implement custom syntax highlighting, it's highly configurable, and it just works.

For now, I'm just going to enable word-wrap by default in my projects that use AvalonEdit so I don't have to deal with the wonky horizontal scrolling. I'm not developing a full-fledged text editor but just need a small component to show some syntax highlighted code. But if I was doing anything more advanced, I would be very frustrated.

I may fork this project as a whole and see if I can't implement what I need on my own if you and your team are committed to retaining this weird default behavior.

Sorry if this comes off as harsh. I have a lot of appreciation for what your team has created. AvalonEdit is great. Let's make it more great! (Please!)

Jay

@dgrunwald
Copy link
Member

I think you're underestimating just how crappy WPF text layout performance is.
This isn't just about huge (~100MB) files; even medium-sized files (~1MB) would see noticeable slowdown from doing text layout over the whole document.

What we could do (but it's a non-trivial effort) is to treat the horizontal scrollbar the same way as we do the vertical scrollbar. The vertical scrollbar has a similar problem: we don't know how tall a line is until we've layouted it (esp. if word wrap is enabled), but we start with a guess and then refine that guess when the line is rendered. And we keep the improved guess around, so that the vertical scrollbar feels stable except when a particularly long wrapped line is scrolled into the viewport for the first time.

So I think the proper solution is:

  • additionally store the line width in the HeightTree
  • augment the tree to track the maximum line width
  • similar to the line height, start with a rough guess (e.g. line.Length * WideSpaceWidth)
  • after rendering a line, update the line width along with the line height

@futuremotiondev
Copy link

I think you're underestimating just how crappy WPF text layout performance is. This isn't just about huge (~100MB) files; even medium-sized files (~1MB) would see noticeable slowdown from doing text layout over the whole document.

You're right. I don't know much about the internals of the component and I should probably look through the code more. I didn't know that text layout in WPF suffers from these kind of bottlenecks. I keep hearing from other developers that WPF is the way forward, and so I guess I incorrectly assumed that implementing what I outlined above wouldn't be limited by WPF itself.

What we could do (but it's a non-trivial effort) is to treat the horizontal scrollbar the same way as we do the vertical scrollbar. The vertical scrollbar has a similar problem: we don't know how tall a line is until we've layouted it (esp. if word wrap is enabled), but we start with a guess and then refine that guess when the line is rendered. And we keep the improved guess around, so that the vertical scrollbar feels stable except when a particularly long wrapped line is scrolled into the viewport for the first time.

That sounds like a great step forward to me. I have word wrap enabled on one of my projects right now and it doesn't feel unstable, even with long wrapped lines.

So I think the proper solution is:
additionally store the line width in the HeightTree
augment the tree to track the maximum line width
similar to the line height, start with a rough guess (e.g. line.Length * WideSpaceWidth)
after rendering a line, update the line width along with the line height

I would be ecstatic if you could implement the above solution. I understand it's non-trivial and I appreciate all the work put into the project, but I think it would really improve the component greatly.

I really appreciate you being receptive to looking at changing this behavior.

@sagarkardani
Copy link

sagarkardani commented Jul 5, 2023

I am also facing this issue. But I am having more problems with Vertical Scrollbar. Scrollbar resizing behaviour will become more prominent when WordWrap is set to true. Because when long wrapped line is first time scrolled into the viewport, then whole Height Tree is readjusted and according to that Vertical scrollbar is also resizing. As the scroll progress the Vertical Scrollbar becomes more smaller.

Another problem with this behaviour is textEditor.ScrollToLine(int lineNumber) is also not working consistently and some times it misses the line and brings some another part of the editor into the view. So I wrote some helper methods to scroll to some line consistently

code

I am always using WordWrap true with cursor already shifted at my desired scroll location. So below method will help me to scroll there.

        private async void ForceScrollToLine(TextEditor textEditor, int line)
        {
            textEditor.ScrollToLine(line);

            await Task.Delay(1);

            TextViewPosition? start = textEditor.TextArea.TextView.GetPosition(new Point(0, 0) + textEditor.TextArea.TextView.ScrollOffset);
            TextViewPosition? end = textEditor.TextArea.TextView.GetPosition(new Point(textEditor.TextArea.TextView.ActualWidth, textEditor.TextArea.TextView.ActualHeight) + textEditor.TextArea.TextView.ScrollOffset);

            int startOffset = start != null ? textEditor.Document.GetOffset(start.Value.Location) : textEditor.Document.TextLength;
            int endOffset = end != null ? textEditor.Document.GetOffset(end.Value.Location) : textEditor.Document.TextLength;

            if ((textEditor.TextArea.Caret.Offset < startOffset) || (textEditor.TextArea.Caret.Offset > endOffset))
            {
                await ForceScrollToLine(textEditor, line);
            }
        }

I also want to draw Highlighting Annotations on Vertical Scrollbar. If Vertical Scrollbar / Height Tree details are not stable, then one cannot draw Highlighting Annotations on Vertical Scrollbar because as the scroll progress and Height Tree gets recalculated, one would also have to update the locations of this Annotations and this will look like Annotations are moving on scrollbar. This does not seem to be the right behaviour. I have already mentioned my requirement here.

@sonofachuck
Copy link
Author

sonofachuck commented Jul 6, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants