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

docs(examples): show layout constraints #393

Merged
merged 1 commit into from
Aug 13, 2023

Conversation

joshka
Copy link
Member

@joshka joshka commented Aug 11, 2023

Shows the way that layout constraints interact visually

example

Review Notes

I'm not sure if this is "good" as an example for users to get value out of the code, as it isn't super simple code. But it covers a reasonable combination of all constraints. It doesn't cover layout margins, and situations where constraints cause gaps (e.g. when Percentage results in a size < full cell width).

Inspired by the following issues:

@kdheepak
Copy link
Collaborator

kdheepak commented Aug 11, 2023

The screen shot looks great! For me personally something that would also be useful is describing in the documentation the math of the linear program for solving the constraints.

I’m happy to take a stab at that over the weekend.

@codecov
Copy link

codecov bot commented Aug 11, 2023

Codecov Report

Merging #393 (b447c30) into main (3293c6b) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##             main     #393   +/-   ##
=======================================
  Coverage   85.10%   85.10%           
=======================================
  Files          40       40           
  Lines        8727     8727           
=======================================
  Hits         7427     7427           
  Misses       1300     1300           

@joshka
Copy link
Member Author

joshka commented Aug 11, 2023

The screen shot looks great! For me personally something that would also be useful is describing in the documentation the math of the linear program for solving the constraints.

I don't know whether that would necessarily be worth your time, especially since we get pretty close to it with taffy for the cost of significantly less code and the benefit of fixing some annoying gaps. I'm a big fan of simple / obvious code over complex code when possible.

Shows the way that layout constraints interact visually

![example](https://vhs.charm.sh/vhs-1ZNoNLNlLtkJXpgg9nCV5e.gif)
@kdheepak
Copy link
Collaborator

kdheepak commented Aug 11, 2023

Here's a ChatGPT generated solution for the mathematical program:

  1. Definitions:

    • A Rect is an element in the definition below.
    • Every element, i.e. every Rect has a $x$, $y$, $w$, $h$ that represents its left, top, width and height.
    • The direction of layout is either Horizontal or Vertical.
    • Along any direction, there can be $N$ number of Rects or elements.
    • Let $x_i$, $y_i$, $w_i$, $h_i$ represent the x-coordinate, y-coordinate, width, and height of the $i^{th}$ element, respectively.
    • The destination area is defined by $[area_l, area_t, area_r, area_b]$.
    • Depending on the direction, we are interested in calculating what the $x$ and $w$ for each element should be OR what the $y$ or $h$ should be. These are the decision variables in this linear programming problem.
  2. Basic Constraints:
    For each element $i$:

    • $w_i \geq 0$, i.e. width of every rect must be greater than or equal to 0
    • $h_i \geq 0$, i.e. height of every rect must be greater than or equal to 0
    • $x_i \geq area_l$, i.e. the x coordinate of every rect must be greater than the leftmost point in the available area
    • $y_i \geq area_t$, i.e. the y coordinate of every rect must be greater than the topmost point in the available area
    • $x_i + w_i \leq area_r$, i.e. the x + width of every rect must be less than the rightmost point in the available area
    • $y_i + h_i \leq area_b$, i.e. the y + height of every rect must be less than the bottommost point in the available area
  3. For the first element:
    If direction = Horizontal:

    • $x_1 = area_l$

    If direction = Vertical:

    • $y_1 = area_t$
  4. If the layout expands to fill:
    For the last element $n$:
    If direction = Horizontal:

    • $x_n + w_n = area_r$

    If direction = Vertical:

    • $y_n + h_n = area_b$
  5. Element adjacency:
    We do not want any overlapping elements. So

    if direction = Horizontal:
    For every consecutive pair $(i, i+1)$:

    • $x_i + w_i = x_{i+1}$

    if direction = Vertical:
    For every consecutive pair $(i, i+1)$:

    • $y_i + h_i = y_{i+1}$
  6. Special size constraints for each element $i$ based on the layout:
    If direction = Horizontal:

    • $y_i = area_t$
    • $h_i = area_b - area_t$

    If direction = Vertical:

    • $x_i = area_l$
    • $w_i = area_r - dest_l$

    Depending on the type of constraint for the element:

    • For Length: $dimension_i = value$ where dimension is width for horizontal and height for vertical.
    • For Percentage: $dimension_i = percentage \times dimension$
    • For Ratio: $dimension_i = (dimension \times numerator) / denominator$
    • For Min: $dimension_i \geq value$
    • For Max: $dimension_i \leq value$

When I did this in Julia, I added one additional constraint. I added a weak constraint saying all widths should be the same for each element for horizontal layouts OR all heights should be the same for each element for vertical layouts. Because it is a weak constraint, it is the last to take precedence. That seemed to give me results that I felt were more intuitive or what a user might naturally expect.

@kdheepak
Copy link
Collaborator

This talk on YouTube is a great resource for understanding why Cassowary is typically used for this kind of problem, and gives some insight into the math above: https://www.youtube.com/watch?v=gxfyb3ipUFg

@joshka joshka added this pull request to the merge queue Aug 13, 2023
Merged via the queue into ratatui-org:main with commit 10dbd6f Aug 13, 2023
30 checks passed
@joshka
Copy link
Member Author

joshka commented Aug 13, 2023

Merging this to help make it easier to visually look at various layout changes.

@joshka joshka deleted the layout-example branch August 13, 2023 07:39
@joshka joshka added this to the v0.23.0 milestone Aug 21, 2023
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

Successfully merging this pull request may close these issues.

None yet

3 participants