There should be a way to get horizontally-scrollable trees using only XUL

NEW
Unassigned

Status

()

Core
XUL
7 years ago
2 months ago

People

(Reporter: crussell, Unassigned)

Tracking

(Blocks: 1 bug)

Firefox Tracking Flags

(Not tracked)

Details

(URL)

Attachments

(1 attachment)

(It occurred to me yesterday that there's no bug against Gecko for this, only stuff like bug 112832.)

The gist is that it's not possible to resize tree columns to achieve a horizontally scrollable tree unless the tree consumer writes some JS to handle it; there's no way to use XUL to specify a tree whose columns behave, e.g., like the GNOME file manager (other system file managers work similarly).

I'm attaching a video to demonstrate how resizing the columns can cause the tree "canvas" to grow outside the contents of the viewport and allow horizontal scrolling.
No attachment, due to file size.  You'll have to deal with video from a third-party host.

Demonstration of a tree with proper basic support for horizontal scrolling (GNOME file manager)
http://tinyvid.tv/show/2y2ao3r5hoknv
Tree with conditional horizontal growth based on a preferred width threshold (GNOME file manager)
http://tinyvid.tv/show/jlj0plk3owj6

Note how in this demonstration, I am able to resize the Date Modified column to a preferred width smaller than its current effective width.  Even though I've resized it (to a point somewhere near the minutes–seconds separator of the timestamp in the first row's cell), it still has an effective width such that it fills the whole tree viewport.  When I resize the first column to a larger width, it subtracts from the padding provided by the difference between the last column's preferred width and the effective width, until it reaches the threshold of the preferred width, at which point, it causes the tree to expand outside its viewport and a horizontal scrollbar appears.
The tree frame code can be fixed to handle this, but it's also doable in XBL by fixing the tree binding.  For the past year, I've been sitting on a working prototype that takes the latter approach.
Oh, and to preempt any mentions of bug 112832, that looks like it dealt with adding horizontal scrolling to the tree frame, but it doesn't deal with stuff like what's mentioned in comment 2, i.e., expanding the last column to fill the tree viewport.

In fact, when I last looked at it, the current implementation doesn't have something like what I've described as preferred width and effective width.  It's all the same, and if the computed sum of all treecol widths is less than the tree viewport width, you get a bunch of dead space filling a gap between the last column and the colpicker/vertical scrollbar.

That's all assuming you're actually specifying widths on columns.  sdwilsh mentions in bug 348764, comment 5 that even the above completely falls apart when you start considering flex columns (which is just about the only way things are ever specified—nobody hardcodes widths onto their columns, for good reason).

It seems to me that what we need here is a way for XUL authors to
  a) specify their columns just as they do now using flex, i.e., that achieves
     widths relative to each other  and columns that flex when the container
     is resized, and
  b) add an attribute (hgrow="true"?) that means, "Hey, allow the tree to
     behave like this".

Comment 5

7 years ago
That's not what I see. What I see is a tree with four statically sized columns. You resize the first column and then you resize the third column.

You can do this already without any extra script, however it's probably under or undocumented. You'll need to remove all the flex from all of your columns. You may want to set an initial width on your columns (they will default to their label's width). And you'll need to set resizeafter="grow" on all the splitters. And you'll want to add an extra splitter to the end of the tree columns, so that you'll always be able to resize the last column.

And I need to fix the Modern theme so that this all displays correctly...
Created attachment 524026 [details]
dead space after the last column

(In reply to comment #5)
> That's not what I see. What I see is a tree with four statically sized columns.
> You resize the first column and then you resize the third column.

In contrast to what?

> You can do this already without any extra script

> And I need to fix the Modern theme so that this all displays correctly...

Classic on GTK2 then, too, because the attachment shows what happens.  Notice that it's the full column that's cut; the cell contents get elided, too.  It's not just a case of the treecol header not extending over all the way.  The prototype I mention in comment 3 messes with column minwidths to achieve the same effect as what can be seen in the two videos.

Comment 7

7 years ago
(In reply to comment #6)
> (In reply to comment #5)
> > That's not what I see. What I see is a tree with four statically sized columns.
> > You resize the first column and then you resize the third column.
> In contrast to what?
Well, your comment suggested that you'd resized the fourth column.

> > You can do this already without any extra script
> > And I need to fix the Modern theme so that this all displays correctly...
> Classic on GTK2 then, too, because the attachment shows what happens.
And on Windows too. Probably nobody ever tried the feature out :-(

> Notice that it's the full column that's cut; the cell contents get elided, too.
The ellipsing is expected, at least by comparison with Windows list views, which always ellipse the last column even though "there is space".

> It's not just a case of the treecol header not extending over all the way.
Interesting... I compared with Windows listviews, and they have a "fake" infinitely wide treecol header that takes up any space. This would be almost straightforward to implement in XBL, but a little tweaking is necessary to prevent the fake header from being clickable or draggable, and I can't see a way to automatically hide the fake header if the existing columns flex.

> The prototype I mention in comment 3 messes with column minwidths to achieve
> the same effect as what can be seen in the two videos.
Not sure what minwidths have to do with anything.

(In reply to comment #4)
> It seems to me that what we need here is a way for XUL authors to
>   a) specify their columns just as they do now using flex, i.e., that achieves
>      widths relative to each other and columns that flex when the container
>      is resized, and
>   b) add an attribute (hgrow="true"?) that means, "Hey, allow the tree to
>      behave like this".
Well, the box model can't really cope with this, since the unbounded resizability conflicts with flexibility.
(In reply to comment #7)
> (In reply to comment #6)
> > (In reply to comment #5)
> > > That's not what I see. What I see is a tree with four statically sized columns.
> > > You resize the first column and then you resize the third column.
> > In contrast to what?
> Well, your comment suggested that you'd resized the fourth column.

In which video?  In the first one (http://tinyvid.tv/show/2y2ao3r5hoknv), I do resize the first and third.  The fourth one is the Date Modified column, which I mentioned in comment 2, but that was referring the second video I linked (http://tinyvid.tv/show/jlj0plk3owj6), where I demonstrate setting on the fourth column a preferred width smaller than its effective width, and how elastic the layout is when resizing other columns until it reaches that threshold.

> Interesting... I compared with Windows listviews, and they have a "fake"
> infinitely wide treecol header that takes up any space.

Bug 307062 mentions this, too.  In another related tree bug that I can't think of at the moment, a comment makes note that we deliberately deviate from some system conventions.  Following the approach taken by the Windows listview seems to me to be one of these cases.  It appears to me to be obviously suboptimal to how the GNOME file manager is shown to behave in this area.

> This would be almost
> straightforward to implement in XBL, but a little tweaking is necessary to
> prevent the fake header from being clickable or draggable, and I can't see a
> way to automatically hide the fake header if the existing columns flex.
> 
> > The prototype I mention in comment 3 messes with column minwidths to achieve
> > the same effect as what can be seen in the two videos.
> Not sure what minwidths have to do with anything.

Implementation detail.  It's just how things work in the prototype I worked up, so that it could cope with things like flex...

> (In reply to comment #4)
> > It seems to me that what we need here is a way for XUL authors to
> >   a) specify their columns just as they do now using flex, i.e., that achieves
> >      widths relative to each other and columns that flex when the container
> >      is resized, and
> >   b) add an attribute (hgrow="true"?) that means, "Hey, allow the tree to
> >      behave like this".
> Well, the box model can't really cope with this, since the unbounded
> resizability conflicts with flexibility.

That's what I mean to say the JS is for.  If you *do* want to achieve these things, it's certainly possible for tree consumers to get that behavior, but consumers have to do it themselves, rather than it being a feature of vanilla trees.

(hgrowable trees prototyped in an extended tree binding)
http://tinyvid.tv/show/3h9c0b50vbi1h

Comment 9

7 years ago
Ah, sorry, I hadn't noticed that the random URL suffixes were different.
(In reply to comment #8)
> (http://tinyvid.tv/show/jlj0plk3owj6), where I demonstrate setting on the
> fourth column a preferred width smaller than its effective width, and how
> elastic the layout is when resizing other columns until it reaches that
> threshold.
...
> > Not sure what minwidths have to do with anything.
> Implementation detail.  It's just how things work in the prototype I worked up,
> so that it could cope with things like flex...
Right, so if you only flexed the last visible column, and you set a minimum width, then you could get an effect similar to the above video. But the splitter code wouldn't understand that and the column wouldn't be resizable.

> (hgrowable trees prototyped in an extended tree binding)
> http://tinyvid.tv/show/3h9c0b50vbi1h
So what happens to the columns if you resize the pane/window? (Or did you size the columns to fit before starting the video?)
(In reply to comment #10)
> (In reply to comment #8)
> > (http://tinyvid.tv/show/jlj0plk3owj6), where I demonstrate setting on the
> > fourth column a preferred width smaller than its effective width, and how
> > elastic the layout is when resizing other columns until it reaches that
> > threshold.
> ...
> > > Not sure what minwidths have to do with anything.
> > Implementation detail.  It's just how things work in the prototype I worked up,
> > so that it could cope with things like flex...
> Right, so if you only flexed the last visible column, and you set a minimum
> width, then you could get an effect similar to the above video.

Yeah.

> But the
> splitter code wouldn't understand that and the column wouldn't be resizable.

Mmm... it does, though.  It's not shown in the prototype video, but the two aspects demonstrated in the two videos of the GNOME file manager are things that I have working.  There're a few places where last col stuff needs to be special-cased.

> > (hgrowable trees prototyped in an extended tree binding)
> > http://tinyvid.tv/show/3h9c0b50vbi1h
> So what happens to the columns if you resize the pane/window? (Or did you size
> the columns to fit before starting the video?)

Same thing that happens with a vanilla tree with flex columns.
(In reply to comment #11)
> > But the
> > splitter code wouldn't understand that and the column wouldn't be resizable.
> Mmm... it does, though.
Well, not with the current setup, which is what I was trying it on, and I don't see offhand how you could change it and still have the last column flexible.

> > > (hgrowable trees prototyped in an extended tree binding)
> > > http://tinyvid.tv/show/3h9c0b50vbi1h
> > So what happens to the columns if you resize the pane/window? (Or did you size
> > the columns to fit before starting the video?)
> Same thing that happens with a vanilla tree with flex columns.
Sorry, I don't understand... a vanilla tree with flex columns won't scroll, so when you resize the pane all the columns flex to fit.
(In reply to comment #12)
> (In reply to comment #11)
> > > But the
> > > splitter code wouldn't understand that and the column wouldn't be resizable.
> > Mmm... it does, though.
> Well, not with the current setup, which is what I was trying it on, and I don't
> see offhand how you could change it and still have the last column flexible.
> 
> > > > (hgrowable trees prototyped in an extended tree binding)
> > > > http://tinyvid.tv/show/3h9c0b50vbi1h
> > > So what happens to the columns if you resize the pane/window? (Or did you size
> > > the columns to fit before starting the video?)
> > Same thing that happens with a vanilla tree with flex columns.
> Sorry, I don't understand... a vanilla tree with flex columns won't scroll

It will if all the cols have a minwidth set where their sum is greater than the space afforded by the tree.
(In reply to comment #12)
> (In reply to comment #11)
> > > But the
> > > splitter code wouldn't understand that and the column wouldn't be resizable.
> > Mmm... it does, though.
> Well, not with the current setup, which is what I was trying it on, and I don't
> see offhand how you could change it and still have the last column flexible.

When the splitter enters the drag state, the resizing col's flex is temporarily removed until the drag state ends, then it's reinstated.  The minwidth is also removed, then readded to be the same as width at the end of the drag.

If the resizing col is the last one, flex gets removed as it does with the other columns, but if during the drag, the width drops below the width required to give the appearance of a completely filled treecols element (i.e., it would leave a gap as in attachment 524026 [details]), the flex is readded.
I see how that would work, although it does feel a little hackish to me.
(In reply to comment #11)
> > > (hgrowable trees prototyped in an extended tree binding)
> > > http://tinyvid.tv/show/3h9c0b50vbi1h
> > So what happens to the columns if you resize the pane/window? (Or did you size
> > the columns to fit before starting the video?)
> 
> Same thing that happens with a vanilla tree with flex columns.

Also, I should point out here that this actually *isn't* the way the GNOME file manager does things.  When you resize the window, the extra space gets added to the first column, and you can't do anything about it—not even drag its splitter to resize it to be any smaller.

(In reply to comment #15)
> I see how that would work, although it does feel a little hackish to me.

Agreed, but then lots of other XUL stuff does stuff in ways that add, remove, and alter attributes.  Does it feel that way just because it's done in XBL which necessitates doing it through adding and removing attributes?  If it were done in the splitter/tree frame code using the same principles, would it be kosher?
(In reply to comment #16)
> (In reply to comment #15)
> > I see how that would work, although it does feel a little hackish to me.
> Agreed, but then lots of other XUL stuff does stuff in ways that add, remove,
> and alter attributes.  Does it feel that way just because it's done in XBL
> which necessitates doing it through adding and removing attributes?  If it were
> done in the splitter/tree frame code using the same principles, would it be
> kosher?
Well, for instance, you want to be able to say "I want this to be able to flex bigger but not smaller, but I want splitters to be able to shrink it", which isn't supported in the current box model.
Over in bug 197123, comment 8 and bug 197123, comment 14, Enn and faaborg note about trying to get this working.

(In a few hours, I'm submitting this as part of my proposal for GSoC, by the way.)
Moving to Core:XUL per https://bugzilla.mozilla.org/show_bug.cgi?id=1455336
Component: XP Toolkit/Widgets: XUL → XUL
You need to log in before you can comment on or make changes to this bug.