~eliasnaur/gio

3 2

Very tall widgets

Details
Message ID
<20200103184030.GA6294@larrymbp14.local>
DKIM signature
missing
Download raw message
Yesterday in the GioUI slack channel[1] I mentioned some performance
problems I'm having with my Gio app (macOS).  I fixed one of them (too
many Layouts!), but another has come up: How to display very tall
widgets, e.g. ~248k pixels?

I'm writing something akin to a terminal.  I run commands and display
the output.  Some of the output is, of course, fairly long.  (In Slack
I mentioned "the bash manpage", which is > 4k lines, ~430 kb, and, as
alluded to above, ~248,000 pixels.)

Initially I did the entire output in a single Theme.Body1 widget.
That was great for short commands, but not for longer ones.  As near
as I could tell, the entire widget was rendered, and then clipped to
fit the window.  When the widget is 111 pixels, no problem; when the
widget is 248k pixels, big problems!  :)

So I tried a List.  That worked better, but still had problems.  The
list is inside another list.  (The list of commands, and each command
is a list of output.)  Well, List sets its vertical maximum constraint
to "inf", 1e6.  So the inner list thought it was a million pixels tall
and rendered the whole thing every time, just like Body was doing.

I set the inner List's max height to be the real window height, but
since it's a ScrollToEnd list, that also didn't work.  It did work
when the output was longish (> one window), but failed when it wasn't
(< one window), because the shorter command output always took up a
whole window, even though it might only be 111 pixels tall.

(And before I tried setting the inner List's max height, all commands
always took up 1e6 pixels in height, which also sucked.)

Instead of an inner List, I also tried a Flex, but that also always
lays out all of its children, and so suffered the same problem as the
one big Body1 widget.

So, suggestions for really tall widgets?  Am I doing something wrong?
Is there some way to get a Flex to not render all its children?  Do I
need to flatten my widget structure so that there's only the one outer
list?  (That would kind of suck.)  Can List be changed so that it
doesn't set its height (actually its "main axis") to inf but still
works when you do a hundred-odd pixels with ScrollToEnd?

Right now, the only thing I know of that conditionally renders only
some of its children is List.  A ScrollToEnd list inside another
ScrollToEnd list is problematic, in the way I've mentioned above.  The
path of least resistance seems like changing the inner list to not
take up its entire maximum height (1e6) when it's ScrollToEnd.

(Really, though, the inner item should be a Flex.  It shouldn't scroll
on its own.  I may later have a display option where each command does
scroll independently in a smaller viewport, but not at the moment.)

Thanks for any help or advice!

-- Larry

[1] Link to Slack discussion:
https://gophers.slack.com/archives/CM87SNCGM/p1578004230033500
Details
Message ID
<BZMHCD9FEH1L.JRPS3OQC2XMB@toolbox>
In-Reply-To
<20200103184030.GA6294@larrymbp14.local> (view parent)
DKIM signature
pass
Download raw message
On Fri Jan 3, 2020 at 1:40 PM, Larry Clapp wrote:
> I'm writing something akin to a terminal. I run commands and display
> the output. Some of the output is, of course, fairly long. (In Slack
> I mentioned "the bash manpage", which is > 4k lines, ~430 kb, and, as
> alluded to above, ~248,000 pixels.)
>
> 
> Initially I did the entire output in a single Theme.Body1 widget.
> That was great for short commands, but not for longer ones. As near
> as I could tell, the entire widget was rendered, and then clipped to
> fit the window. When the widget is 111 pixels, no problem; when the
> widget is 248k pixels, big problems! :)
>
> 
> So I tried a List. That worked better, but still had problems. The
> list is inside another list. (The list of commands, and each command
> is a list of output.) Well, List sets its vertical maximum constraint
> to "inf", 1e6. So the inner list thought it was a million pixels tall
> and rendered the whole thing every time, just like Body was doing.
>
> 
> I set the inner List's max height to be the real window height, but
> since it's a ScrollToEnd list, that also didn't work. It did work
> when the output was longish (> one window), but failed when it wasn't
> (< one window), because the shorter command output always took up a
> whole window, even though it might only be 111 pixels tall.
>

Why does the inner child take up the entire window? The outer List does pass
inf (1e6) for the max height, but you should be able to pass 0 as the min
height.

In any case, I don't think an inner List or Flex is the correct solution.
See below.

> 
> (And before I tried setting the inner List's max height, all commands
> always took up 1e6 pixels in height, which also sucked.)
>
> 
> Instead of an inner List, I also tried a Flex, but that also always
> lays out all of its children, and so suffered the same problem as the
> one big Body1 widget.
>
> 
> So, suggestions for really tall widgets? Am I doing something wrong?
> Is there some way to get a Flex to not render all its children? Do I
> need to flatten my widget structure so that there's only the one outer
> list? (That would kind of suck.) Can List be changed so that it
> doesn't set its height (actually its "main axis") to inf but still
> works when you do a hundred-odd pixels with ScrollToEnd?
>

From your description, I would expect only the one outer List: your "inner
Lists" really are part of the outer List, layout-wise. And Flex draws all its
children. What sucks about that setup?

-- elias
Details
Message ID
<20200104160006.GA7122@larrymbp14.local>
In-Reply-To
<BZMHCD9FEH1L.JRPS3OQC2XMB@toolbox> (view parent)
DKIM signature
missing
Download raw message
On Fri, Jan 03, 2020 at 10:38:54PM +0100, Elias Naur wrote:
> On Fri Jan 3, 2020 at 1:40 PM, Larry Clapp wrote:
> > I set the inner List's max height to be the real window height,
> > but since it's a ScrollToEnd list, that also didn't work. It did
> > work when the output was longish (> one window), but failed when
> > it wasn't (< one window), because the shorter command output
> > always took up a whole window, even though it might only be 111
> > pixels tall.
> >
> 
> Why does the inner child take up the entire window? The outer List
> does pass inf (1e6) for the max height, but you should be able to
> pass 0 as the min height.

I don't change min height in my code.  I think it defaults to 0.  So I
don't think that'd help?

> In any case, I don't think an inner List or Flex is the correct
> solution.  See below.
> 
> > So, suggestions for really tall widgets? Am I doing something
> > wrong?  Is there some way to get a Flex to not render all its
> > children? Do I need to flatten my widget structure so that there's
> > only the one outer list? (That would kind of suck.) Can List be
> > changed so that it doesn't set its height (actually its "main
> > axis") to inf but still works when you do a hundred-odd pixels
> > with ScrollToEnd?
> 
> From your description, I would expect only the one outer List: your
> "inner Lists" really are part of the outer List, layout-wise. And
> Flex draws all its children. What sucks about that setup?

In Go terms, I have a slice of commands, and each command has a slice
of output widgets, one per line.  I would like to be able to add other
widgets to decorate each command (e.g. start time, elapsed time, exit
status, etc), as well as buttons (abort, re-run, etc).

So basically it makes the most sense to me -- perhaps naively -- to
model this as a List of Flex widgets, where each Flex can have the
decorations I mentioned.

Modeling this as One Big List for all commands, and their decorations,
runs counter to both how I've conceived of my layout, and to my
expectations for a windowing toolkit.  (I admit that perhaps my
expectations are wrong.)

It's very possible that I *can* use a List of Flexes, and just need to
tweak the constraints around the Flex, or something.  Or a List of
Lists.  I'm just not sure how, and got tired of experimenting, and
thought I'd ask for help.

I have tried a List within a List.  The scrolling is a little weird.
The outer list and the inner list both scroll at once.  Also once you
have multiple smaller lists (non-overlapping, one after the other) in
a single larger list, the scrolling is similarly weird.  You can see a
similar (or possibly the same?) phenomenon if you run the "kitchen"
app, reduce it to half its regular height, and then scroll up and
down.  The top editor text scrolls at the same time as the outer
content.

In more general terms, my app aside, it does seem like one should be
able to put a bunch of tall Flexes inside a List and not have the
whole Flex be rendered.  Would you agree or disagree with that?  And
if you disagree, what would you suggest for displaying large amounts
of content efficiently?

(Again, I'm just asking for advice.  I'm fairly new to frontend work,
and all my experience until Gio has been in a web browser, where this
sort of thing isn't as big of a problem, as near as I can tell.)

Thanks for your help!

-- Larry
Details
Message ID
<BZN5UIQ3XK10.EM3ZHOUUSC0W@toolbox>
In-Reply-To
<20200104160006.GA7122@larrymbp14.local> (view parent)
DKIM signature
pass
Download raw message
On Sat Jan 4, 2020 at 11:00 AM, Larry Clapp wrote:
> On Fri, Jan 03, 2020 at 10:38:54PM +0100, Elias Naur wrote:
> > On Fri Jan 3, 2020 at 1:40 PM, Larry Clapp wrote:
> > > I set the inner List's max height to be the real window height,
> > > but since it's a ScrollToEnd list, that also didn't work. It did
> > > work when the output was longish (> one window), but failed when
> > > it wasn't (< one window), because the shorter command output
> > > always took up a whole window, even though it might only be 111
> > > pixels tall.
> > >
> > 
> > Why does the inner child take up the entire window? The outer List
> > does pass inf (1e6) for the max height, but you should be able to
> > pass 0 as the min height.
>
> 
> I don't change min height in my code. I think it defaults to 0. So I
> don't think that'd help?
>
> 
> > In any case, I don't think an inner List or Flex is the correct
> > solution.  See below.
> > 
> > > So, suggestions for really tall widgets? Am I doing something
> > > wrong?  Is there some way to get a Flex to not render all its
> > > children? Do I need to flatten my widget structure so that there's
> > > only the one outer list? (That would kind of suck.) Can List be
> > > changed so that it doesn't set its height (actually its "main
> > > axis") to inf but still works when you do a hundred-odd pixels
> > > with ScrollToEnd?
> > 
> > From your description, I would expect only the one outer List: your
> > "inner Lists" really are part of the outer List, layout-wise. And
> > Flex draws all its children. What sucks about that setup?
>
> 
> In Go terms, I have a slice of commands, and each command has a slice
> of output widgets, one per line. I would like to be able to add other
> widgets to decorate each command (e.g. start time, elapsed time, exit
> status, etc), as well as buttons (abort, re-run, etc).
>
> 
> So basically it makes the most sense to me -- perhaps naively -- to
> model this as a List of Flex widgets, where each Flex can have the
> decorations I mentioned.
>
> 
> Modeling this as One Big List for all commands, and their decorations,
> runs counter to both how I've conceived of my layout, and to my
> expectations for a windowing toolkit. (I admit that perhaps my
> expectations are wrong.)
>
> 
> It's very possible that I *can* use a List of Flexes, and just need to
> tweak the constraints around the Flex, or something. Or a List of
> Lists. I'm just not sure how, and got tired of experimenting, and
> thought I'd ask for help.
>
> 
> I have tried a List within a List. The scrolling is a little weird.
> The outer list and the inner list both scroll at once. Also once you
> have multiple smaller lists (non-overlapping, one after the other) in
> a single larger list, the scrolling is similarly weird. You can see a
> similar (or possibly the same?) phenomenon if you run the "kitchen"
> app, reduce it to half its regular height, and then scroll up and
> down. The top editor text scrolls at the same time as the outer
> content.
>

The list-inside-list is a notorious problem in UIs. I intend to change the
pointer package ops to only route the scroll wheel events to the topmost list.
However, that still leaves problems such as what happens when the topmost
list reaches one of its ends.

> 
> In more general terms, my app aside, it does seem like one should be
> able to put a bunch of tall Flexes inside a List and not have the
> whole Flex be rendered. Would you agree or disagree with that? And
> if you disagree, what would you suggest for displaying large amounts
> of content efficiently?
>

The fundamental reason large Flexes renders all its children is that it doesn't
know where its "visible window" is positioned relative to its children. On the
other hand, Lists track their visible windows, but they're difficult to embed
in other Lists.

Perhaps a tweak to your program, to Flex and/or List or a new layout object is
the solution. I don't know for sure. Can you create a program demonstrating the
issue? I feel the risk of my misunderstanding your issue is too high without
one.

-- elias