Home » U++ Library support » U++ Widgets - General questions or Mixed problems » How would I virtualize a scrollable view to dynamically load Ctrls?
How would I virtualize a scrollable view to dynamically load Ctrls? [message #58431] |
Thu, 19 May 2022 19:07  |
jjacksonRIAB
Messages: 218 Registered: June 2011
|
Experienced Member |
|
|
Quick example:
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
struct App : TopWindow {
ScrollBar sb;
Array<RichTextCtrl> items;
int GetLineHeight() {
return 25;
}
void Sync() {
int startY = 10;
Rect pr = GetRect();
auto sz = GetSize();
for(RichTextCtrl& item : items) {
Rect r = item.GetRect();
item.SetRect(r.left, startY - sb, pr.GetWidth(), item.GetHeight(sz.cx));
startY += r.GetHeight() + 5;
}
sb.SetTotal(startY);
}
void Paint(Draw& w) override {
Size sz = GetSize();
w.DrawRect(sz, SWhite());
Sync();
}
void Layout() override {
sb.SetPage(GetSize().cy);
}
void MouseWheel(Point, int zdelta, dword) override {
sb.Wheel(zdelta);
}
bool Key(dword key, int) override {
return sb.VertKey(key);
}
App() {
Sizeable().Zoomable();
for(int i = 0; i < 1000; i++) {
RichTextCtrl& item = items.Create<RichTextCtrl>();
item.SetData(
Format(
"[@(%d.%d.%d) Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et "
"dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip "
"ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu "
"fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
"mollit anim id est laborum.]",
(int)Random(255), (int)Random(255), (int)Random(255))
);
item.SetZoom(Zoom(1, 1));
item.HSizePos(0, 0).VSizePos(0, 0);
item.SetRect(0, 0, 0, item.GetHeight(250));
item.IgnoreMouse();
Add(item);
}
Sync();
sb.Enable();
sb.WhenScroll = [this] { Sync(); };
sb.SetLine(GetLineHeight());
AddFrame(sb);
}
};
GUI_APP_MAIN {
App app;
app.SetRect(0, 0, 250, 500);
app.Run();
}
I don't know if there is any facility built into U++ for this already but I'd like to dynamically load and unload a bunch of Ctrls as I scroll (web equivalent a virtual scroller) so that I don't have a bunch of redraws of Ctrls that aren't visible in the view. As you can see from the example it can get quite expensive to resize the window if it has thousands of controls.
How would I accomplish this?
|
|
|
Re: How would I virtualize a scrollable view to dynamically load Ctrls? [message #58479 is a reply to message #58431] |
Tue, 31 May 2022 11:13   |
 |
mirek
Messages: 13964 Registered: November 2005
|
Ultimate Member |
|
|
Placing those text in Paint is not a good idea. The time is spent in RichTextCtrl::GetHeight, which is slow. I have tried to optimise
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
struct App : TopWindow {
ScrollBar sb;
Array<RichTextCtrl> items;
int GetLineHeight() {
return 25;
}
void Scroll() {
Size sz = GetSize();
int sy = sb;
int y = 0;
for(RichTextCtrl& item : items) {
int h = item.GetRect().GetHeight();
if(sz.cx && y + h > sy && y < sy + sz.cy) {
item.Show();
item.SetRect(0, y - sy, sz.cx, h);
}
else
item.Hide();
y += h + 5;
}
}
void Paint(Draw& w) override {
Size sz = GetSize();
w.DrawRect(sz, SWhite());
}
void Layout() override {
Size sz = GetSize();
sb.SetPage(sz.cy);
if(sz.cx) {
int y = 0;
for(RichTextCtrl& item : items) { // compute the height - that can be slow
Rect r = item.GetRect();
if(r.GetWidth() != sz.cx) {
int h = item.GetHeight(sz.cx);
item.SetRect(0, 0, sz.cx, h);
item.Hide();
y += h + 5;
}
}
sb.SetTotal(y);
}
Scroll();
}
void MouseWheel(Point, int zdelta, dword) override {
sb.Wheel(zdelta);
}
bool Key(dword key, int) override {
return sb.VertKey(key);
}
App() {
Sizeable().Zoomable();
for(int i = 0; i < 10000; i++) {
RichTextCtrl& item = items.Create<RichTextCtrl>();
item.SetData(
Format(
"[@(%d.%d.%d) Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et "
"dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip "
"ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu "
"fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
"mollit anim id est laborum.]",
(int)Random(255), (int)Random(255), (int)Random(255))
);
item.SetZoom(Zoom(1, 1));
item.SetRect(0, 0, 0, 0);
item.IgnoreMouse();
Add(item);
}
sb.Enable();
sb.WhenScroll = [this] { Scroll(); };
sb.SetLine(GetLineHeight());
AddFrame(sb);
}
};
GUI_APP_MAIN {
App app;
app.SetRect(0, 0, 250, 500);
app.Run();
}
Which works fine for 10000 texts; with 100000 texts it is slow again, but the time once again is lost in GetHeight - that one basically needs to typeset that paragraph with all typographic rules. I can try to look into it, OTOH as we will need to support advanced composition in future, chances are it will only get slower then.
Mirek
|
|
|
|
|
Re: How would I virtualize a scrollable view to dynamically load Ctrls? [message #58487 is a reply to message #58483] |
Tue, 31 May 2022 21:27   |
jjacksonRIAB
Messages: 218 Registered: June 2011
|
Experienced Member |
|
|
mirek wrote on Tue, 31 May 2022 14:39I am afraid that with thousands of paragraphs, it will still be slow determining the height for given with (e.g. RichTextCtrl needs to do that in Layout anyway). Note that if you load some really big text in MS Word or OpenOffice writer, it can be slow as well before he reformats everything. In you current example, you need to typeset about 4 millions glyphs... 
It is strange it is slow on your machine though. What exactly is slow, scrolling?
Mirek
Scrolling is fine. Resizing just kills it. This is on linux though, I don't know if you were running it on Windows. KDE, cinnamon, lxde - doesn't matter on any DE I've tested even with compositing turned off.
But yeah, given the amount it has to do to the text I'm not surprised it bogs down. That's a lot of work to do just for a transitional effect. I thought the problem, other than the sheer number of items was in GetHeight too, promise to use the profiler code in the future to know for sure. One thing I was really impressed with was how little memory it used.
|
|
|
Re: How would I virtualize a scrollable view to dynamically load Ctrls? [message #58489 is a reply to message #58487] |
Wed, 01 June 2022 15:34   |
 |
mirek
Messages: 13964 Registered: November 2005
|
Ultimate Member |
|
|
jjacksonRIAB wrote on Tue, 31 May 2022 21:27mirek wrote on Tue, 31 May 2022 14:39I am afraid that with thousands of paragraphs, it will still be slow determining the height for given with (e.g. RichTextCtrl needs to do that in Layout anyway). Note that if you load some really big text in MS Word or OpenOffice writer, it can be slow as well before he reformats everything. In you current example, you need to typeset about 4 millions glyphs... 
It is strange it is slow on your machine though. What exactly is slow, scrolling?
Mirek
Scrolling is fine. Resizing just kills it. This is on linux though, I don't know if you were running it on Windows. KDE, cinnamon, lxde - doesn't matter on any DE I've tested even with compositing turned off.
That part is actually not influenced by DE nor system in any way... I believe 99% of time is spent in
RichPara::Lines RichPara::FormatLines(int acx) const
RichText/ParaType.cpp:237
Mirek
|
|
|
Re: How would I virtualize a scrollable view to dynamically load Ctrls? [message #58490 is a reply to message #58489] |
Wed, 01 June 2022 15:57  |
jjacksonRIAB
Messages: 218 Registered: June 2011
|
Experienced Member |
|
|
mirek wrote on Wed, 01 June 2022 15:34jjacksonRIAB wrote on Tue, 31 May 2022 21:27mirek wrote on Tue, 31 May 2022 14:39I am afraid that with thousands of paragraphs, it will still be slow determining the height for given with (e.g. RichTextCtrl needs to do that in Layout anyway). Note that if you load some really big text in MS Word or OpenOffice writer, it can be slow as well before he reformats everything. In you current example, you need to typeset about 4 millions glyphs... 
It is strange it is slow on your machine though. What exactly is slow, scrolling?
Mirek
Scrolling is fine. Resizing just kills it. This is on linux though, I don't know if you were running it on Windows. KDE, cinnamon, lxde - doesn't matter on any DE I've tested even with compositing turned off.
That part is actually not influenced by DE nor system in any way... I believe 99% of time is spent in
RichPara::Lines RichPara::FormatLines(int acx) const
RichText/ParaType.cpp:237
Mirek
Having not tested it myself I'll defer to your experience but my rationale for how it could happen is that perhaps one DE/WM may fire resize events more frequently than another but it was just a guess. More likely your machine is just significantly faster than mine.
|
|
|
Goto Forum:
Current Time: Thu Dec 07 17:44:25 CET 2023
Total time taken to generate the page: 0.02357 seconds
|