Fixes for block select slowness and jumping caret issues #269
No reviewers
Labels
No labels
Area-Accessibility
Area-Build
Area-CodeCompletion
Area-Document
Area-Documentation
Area-Editing
Area-Folding
Area-Highlighting
Area-i18n
Area-Indentation
Area-NetFx
Area-Rendering
Area-Search
Area-Snippets
dependencies
duplicate
Feedback Needed
help wanted
invalid
Issue-Bug
Issue-Discussion
Issue-Enhancement
Issue-Performance
Issue-Question
on-hold
Resolution-Answered
Resolution-By Design
Resolution-Duplicate
Resolution-Fixed
Resolution-Won't Fix
Up-for-Grabs
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-icsharpcode/AvalonEdit!269
Loading…
Reference in a new issue
No description provided.
Delete branch "zaksmolen/block_select_fixes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This pull request has two fixes in it. The first, in RectangleSelection.cs, fixes an issue where the caret would jump to the top in some large block selections (especially if they were out of the visual). It would set the caret to the default value of a nullable, which put it at the top. This doesn't overwrite the caret position if it's null.
The next fix is a major one, that's been plaguing me for years at this point. Block selections seemed to get exponentially slower based on selection size. A large selection of a few hundred lines would take noticeably a few seconds per character typed. I tracked this down to the
OnDocumentChangedevent in TextArea.cs. Basically, every key press would trigger the event, which would trigger the event on the selection. This meant that every key press would cause a lot of calculating and rendering for every sub-selection within the rectangular selection. By not calling this extra update event for rectangular selections I have been able to do thousands of lines in a selection with no issue. This change has been live in my application for months with no visible side effects.This does not look like a clean solution to the problem. Why should
RectangleSelectionbe a hard-coded exception? If you want to ignore changes forRectangleSelection, you could simply fix this by replacing the body ofRectangleSelection.UpdateOnDocumentChangewithreturn this;.However, I don't like the asymmetry this introduces. All selections get notified and handle document changes except
RectangleSelection, this is rather unexpected, I would argue... I think the better solution would be to fix the actual culprit: Each line is changed individually and produces a separate changed event. This causes a lot of work to be repeated for each line, instead of doing it once, after all lines are changed.Update: I had a look at the code again and I found the reason why this change is not causing any problems:
github.com/icsharpcode/AvalonEdit@9e8ab4b177/ICSharpCode.AvalonEdit/Editing/RectangleSelection.cs (L323)always replaces the selection with a valid one after all changes are made. So I think the best solution would be to changeRectangleSelection.UpdateOnDocumentChangeto simplyreturn this;, but with a comment added that explains this exception.I suspect however that this would fall apart as soon as there would be someone other than the user editing the text in the document while the user has an active rectangular selection.
I'll give that a test on my end!
On Mon, Mar 8, 2021 at 2:28 PM Siegfried Pammer notifications@github.com
wrote:
Another idea: Instead of removing the logic in
UpdateOnDocumentChangeyou could simply clear the selection while editing is in progress... this should not cause any problems, because the selection is replaced after all changes are applied anyway. This way, we correctly respond to changes that are not initiated by user input and get rid of all the extra useless work that is done and makes editing slow. What do you think?I tried that (and , as far as I can tell it seems to work just as fine. I didn't see any issues poking around the sample application but I wasn't sure of a great test for changing text while someone has an active selection. I think I pushed my changes but I'm new to doing pull requests through forked repos.
You could add a DispatcherTimer to the sample application, which modifies the document near the selection every second, or something similar.
Yeh that makes sense, I'll give that a try this afternoon.
On Tue, Mar 9, 2021 at 9:29 AM Siegfried Pammer notifications@github.com
wrote:
I set up a test where I just did a character replacement on the whole text
block in a DispatcherTimer. Here's the behavior I see:
If the selection contains text that's changed, the selection goes away. I
think that makes sense? The content of the selection changed externally
so the selection is no longer valid.
If the selection is just a column, i.e. you're inserting text, it stays
even when the insert happens. This occurs even if your column selection is
right next to the changed characters.
To replicate, I just put this in the constructor of Window1 in the sample
application:
DispatcherTimer changeTestingTimer = new DispatcherTimer();
changeTestingTimer.Interval = TimeSpan.FromSeconds(10);
changeTestingTimer.Tick += delegate { textEditor.Text =
textEditor.Text.Replace('!', '*'); };
changeTestingTimer.Start();
Then I copied about 20 lines of "Welcome to! AvalonEdit!" and could paste
that into the editor and watch it change every 10 seconds while I was doing
different selections.
On Tue, Mar 9, 2021 at 9:32 AM Zak Smolen zaksmolen@gmail.com wrote:
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.