mirror of
https://github.com/rivo/tview.git
synced 2026-04-26 21:35:54 +03:00
[GH-ISSUE #411] Dynamic layouts #299
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/tview#299
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Originally created by @gnojus on GitHub (Feb 24, 2020).
Original GitHub issue: https://github.com/rivo/tview/issues/411
I realized what I'm missing from this package. While it's great for predesigned interfaces, it's not very suitable to create dynamic layouts, for example a chat view.
I was thinking that a primitive could return minimal dimensions to fit it's contents. You could also set for example fixed width and the primitive would recalculate its required height accordingly.
Some primitive, e. g.
Containercould provide stacking primitives and scrolling functionality.Or would this be outside the scope of this package?
@rivo commented on GitHub (Feb 24, 2020):
Pretty much. You're talking about a layout engine as web browser implement them, where sizes propagate down as well as up. It's not just the implementation which is highly sophisticated and therefore way beyond the scope of this project. You will then also need some kind of CSS-like language to describe the layout.
In
GridandFlex, I'm already using some tricks (with negative numbers) to differentiate between proportional and absolute sizes. If you now add to this things like "min-width" and "max-width", "auto", "inherited", or even fun stuff like fractional size units (see "fr" in CSS grids), the complexity will not be manageable anymore (and we'll definitely have to break backwards-compatibility). Maybe you're then better off using Lynx, w3m or something like that.@tslocum commented on GitHub (Feb 24, 2020):
I agree with rivo, but I'm open to adding this functionality to cview if you or anyone else is interested in working on an initial implementation (I'm glad to help).
@gnojus commented on GitHub (Feb 24, 2020):
@rivo ok, I understand.
@tslocum Yes I'm interested in such implementation, and I have been thinking about it lately.
@gnojus commented on GitHub (Feb 29, 2020):
I decided to try and implement this and came up with a simple, but yet very useful solution (at least from my perspective). I only made the basic implementation, because I thought that rivo might actually see this as an useful addition to
tview.The idea:
Primitive:GetWidth(height)andGetHeight(width). These calculate and return the minimum required size accordingly to the given opposite measurement so that it can fully fit all its contents inside such box.Maybe this should be an interface that only some primitives implement, I'm not sure:
GridandFlexwould calculate required width/height by summing all the required sizes by items inside.Container. Acts simmillary to aFlex, has row/column direction and allows to append items with either fixed size or dynamic iffixedSize< 0.Containerwould respect size required by primitives (viaGetWidth/GetHeight) and wouldn't care about fitting items inside - it would just make everything scrollable.Implementation:
You can find basic implementation in https://github.com/Nojus297/tview (branch
dynamic). Its pretty much a copy-paste fromFlex. The only primitives that haveGetWidth/GetHeightactually implemented areTextViewandFlex(Boxonly keeps the default 15:10 ratio) and there is an example using these indemos/containerfolder.I hope you (@rivo) can find some time to look at this and say whether this is a viable addition to tview. If so, I would gladly help to make this. Anyway, let me know you thoughts.
@rivo commented on GitHub (Apr 14, 2020):
So from glancing over your code, your
Containerclass isFlexbut without proportional sizes. You replace them with sizes calculated by the primitives themselves. How are those sizes calculated? Well, in 2D space we have two sizes, width and height. Your suggestion is that given one, primitives can calculate an optimal value for the other one.But the only case where this is actually useful is when calculating the height for a
TextViewgiven a fixed width. ItsGetWidth()function makes much less sense. It even ignores itsheightparameter. No mention on what other primitives are supposed to do (Boxtries to maintain an arbitrary 10:15 ratio. I'm not sure where this choice comes from.)All of this seems to come down to your need to implement a chat view. (Please correct me if I'm wrong.) Isn't a
TextView.GetCurrentHeight()function all you need? You can then use this to update yourFlex/Grid.@gnojus commented on GitHub (Apr 15, 2020):
You are right, the version that I linked previously is far from perfect and doesn't make too much sense. I have made many changes on my local branch, which is now super handy for me, but as I'm developing it I'm now less sure that it actually fits for tview.
This wasn't a good idea, but I changed it to return borders+padding. This way subclassing primitives can subtract this value when calculating their width/height from passed argument and add the opposite to the result.
The previous version shouldn't even work correctly.
Containers (
Flex,Grid,Container,Pages) should sum/get maximum of their contents, depending on the parameter asked. Others might normally return 0 (likeInputfield), therefore I addedminSize/maxSizeparameters toContaineritems, which has higher priority then their wanted-calculated size.I did end up making
percentageparameter forContaineritems, additional tominSize/maxSizeto allow basic spacing (percentage of the free space).This is not too far off, but such functionality could be useful for any dynamically loaded content. The key for me is that you can create custom primitives representing your data, stack them and plop everything to
Container, and let it handle all the sizes and resizes. I'm also using this for a multiline list and scrollable dynamically loaded feed.One bigger issue that came up was that everything started getting inefficient, as many
TextViews had to be reindexed and all the sizes recalculated. This should be solved by some basic caching, but it will ruin the simplicity of the implementation (which isn't simple anymore though).Anyway, I hope that it's a bit clearer now. If you wish, I could tidy up and update the
Containersource, or report later when I'm happy with it myself and it could maybe be useful.@rivo commented on GitHub (Nov 9, 2021):
I realize this would indeed add some convenience to the package. And similar issues have popped up in the past. But I feel like this would require a major overhaul of the layout functionality in
tview. Together with the backwards compatibility mandate, I don't think it's an easy thing to do.I'm leaving this open so I can come back to it at some point.
@rivo commented on GitHub (Dec 12, 2022):
Closing this as it's not on the roadmap in the foreseeable future. We can always reopen once it becomes relevant again.