Scroll views in GUI toolkit
Posted: Fri May 14, 2021 8:04 am
Hello!
I'm in the throes of building my OS's GUI toolkit (on an as-needed basis...).
One useful feature is scroll-views: that is, a view whose visible region is smaller than the total region into which content can be drawn, and which presents a scroll bar to move through the larger region.
In my current implementation, a scroll-view has a maximum "total size" that's set upon initialisation. This is problematic for a few reasons: one obvious one is that the logs viewer application has to delete all the displayed logs periodically, since it exceeds the usable scroll view size.
Just a note on terminology, I'm using "layer" to refer to a pixel buffer. A scroll view has a large "layer" that's rendered into the visible content layer. My new implementation uses the following idea:
1) When a draw request comes in that exceeds the size of the scroll view's backing layer, allocate a new layer with a field indicating the new layer's origin within the scroll view.
2) When executing a draw request, find the backing layer (or layers, if there's overlap) to draw it into
2) When blitting a scroll view onto a visible content view, stitch together the backing layers that should be visible based on the scroll offset and visible content size
The initial proof-of-concept I hacked up works, but is pretty slow as it's doing several O(n) loops to fulfil those steps. I did a bit of reading online and encountered R-trees, which seem like a good way to go.
I'm curious if there's an established approach to do this? Perhaps the canonical way is to simply double the backing layer's size each time it's exceeded and copy over the previous data? This seems simpler, but both have the issue that the logs viewer will use unbounded memory.
Thanks!
I'm in the throes of building my OS's GUI toolkit (on an as-needed basis...).
One useful feature is scroll-views: that is, a view whose visible region is smaller than the total region into which content can be drawn, and which presents a scroll bar to move through the larger region.
In my current implementation, a scroll-view has a maximum "total size" that's set upon initialisation. This is problematic for a few reasons: one obvious one is that the logs viewer application has to delete all the displayed logs periodically, since it exceeds the usable scroll view size.
Just a note on terminology, I'm using "layer" to refer to a pixel buffer. A scroll view has a large "layer" that's rendered into the visible content layer. My new implementation uses the following idea:
1) When a draw request comes in that exceeds the size of the scroll view's backing layer, allocate a new layer with a field indicating the new layer's origin within the scroll view.
2) When executing a draw request, find the backing layer (or layers, if there's overlap) to draw it into
2) When blitting a scroll view onto a visible content view, stitch together the backing layers that should be visible based on the scroll offset and visible content size
The initial proof-of-concept I hacked up works, but is pretty slow as it's doing several O(n) loops to fulfil those steps. I did a bit of reading online and encountered R-trees, which seem like a good way to go.
I'm curious if there's an established approach to do this? Perhaps the canonical way is to simply double the backing layer's size each time it's exceeded and copy over the previous data? This seems simpler, but both have the issue that the logs viewer will use unbounded memory.
Thanks!