Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Make Fixed widgets state their preferred size #19

Closed
petertdavies opened this issue Oct 21, 2015 · 1 comment
Closed

Suggestion: Make Fixed widgets state their preferred size #19

petertdavies opened this issue Oct 21, 2015 · 1 comment

Comments

@petertdavies
Copy link

To be precise, I'm suggesting that:

data Size = Fixed
    | Greedy

be changed to

data Size = Fixed Int
    | Greedy

with the semantics that Fixed n widgets take up n units of space, but will deal with less if they are given it, and Greedy widgets get given whatever is left over after space is allocated to Fixed widgets.

The benefits of the change are:

  • Forcing people to state/calculate the size of Fixed widgets, ensures that Fixed widgets actually have the correct semantics (this would have prevented Scrolling a list widget that isn't at the top of the screen can result in an off-screen selected item #17, for example).
  • It makes boxRenderer much more modular, because it be implemented as:
    1. Calculate the amount of space to give each widget (which can be calculated from the amount of space available and the sizing of each widget)
    2. Render all the widgets
    3. Combine the results
  • Further to the previous point, implementing 2d tables becomes practical (the trick boxRenderer uses doesn't work in 2d)
  • It allows UI elements to degenerate in an orderly fashion when not given enough space. Currently the highest level boxRenderer just crops the resulting table. It would be more sensible if it instead rendered the sub-widgets with less space than requested.

The problems I can foresee are:

  • Every Fixed widget/combinator has to be changed. This is less bad than it seems. Every widget/combinator I found in the library can be implemented easily with the obvious Monoid and Ord instances for Size.
  • Programs that implement Fixed widgets directly are broken.

I'm happy to start implementing this, but I want to make sure you agree with basic idea first.

@jtdaugherty
Copy link
Owner

Thanks for writing this up.

The reason this isn't already the way things are implemented is because it's not as straightforward as one might like. The reason is because the space taken up by a widget (even if it declares Fixed) is not static but depends on the box in which it is rendered. Fixed doesn't exactly mean "the same size every time" or "a fixed size", but rather "not greedy."

For example, a text string that needs to be wrapped has a definite size and won't greedily consume the whole window the way a list might, but it can't say with certainty how big it will be in the future once rendered, because that depends on how much space you give it, and that depends on the layout conditions that exist at rendering time, and those conditions depend on other rendering operations that cannot be statically determined. If you give it enough width, it might be one row high, but it might wrap to two or more rows if not given enough columns. So if it reported a size, anything that used that size to make decisions would get the wrong answer under certain layout conditions.

It allows UI elements to degenerate in an orderly fashion when not given enough space. Currently the highest level boxRenderer just crops the resulting table. It would be more sensible if it instead rendered the sub-widgets with less space than requested.

On this note, I suspect this is going to result in behaviors that are very difficult to predict. For example, would you prefer a dialog box to get cropped, or would you prefer only its buttons to disappear? Which one would be easier to detect visually when you resize the terminal? Cropping at the top level (as a consequence of greed policies, mind you) may seem messy, but I think that makes it more obvious that you just made your terminal too small.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants