Skip to content

Fix axis conversion between horizontal layout types - #44

Merged
geom3trik merged 1 commit into
vizia:mainfrom
ExtraBinoss:fix/overlay-row-axis
Aug 20, 2026
Merged

geom3trik merged 1 commit into
vizia:mainfrom
ExtraBinoss:fix/overlay-row-axis

Conversation

@ExtraBinoss

@ExtraBinoss ExtraBinoss commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fix layout constraint conversion when a parent and child use different LayoutType variants with the same physical main axis.

For example, an Overlay containing a stretched Row currently transposes the available width and height because the conversion checks whether the enum variants are equal. In a 1920 x 1000 container, the row therefore lays out its children against 1000 px of main-axis space instead of 1920 px.

Root cause

Morphorm performs much of its layout in main/cross-axis coordinates. The existing conversion logic assumes that different layout types always use different axis directions:

if parent_layout_type == layout_type {
    (parent_main, parent_cross)
} else {
    (parent_cross, parent_main)
}

That assumption does not match Morphorm's axis model:

  • Row, Overlay, and Grid use width as the main axis.
  • Column uses height as the main axis.

As a result, transitions such as Overlay to Row swap axes even though both layouts are horizontally oriented.

Fix

Compare the physical axis direction instead of comparing LayoutType variants directly. Main and cross constraints are now swapped only when layout crosses between the horizontal group (Row, Overlay, Grid) and Column.

The same predicate is used consistently across child constraint propagation and auto/min/max size resolution, so each path follows the axis semantics already used by NodeExt::main and NodeExt::cross.

Regression coverage

The new test builds the failing hierarchy directly:

Overlay (1920 x 1000)
└── Row (stretch)
    ├── Sidebar (218 px)
    ├── Stage (stretch)
    └── Queue (282 px)

With two 16 px gaps, the flexible stage must receive 1388 px. Before this fix it received 468 px because the row used the parent's 1000 px height as its main-axis constraint.

The patch was also validated in the downstream VIZIA layout that exposed the issue: at a 1920 px window width, its flexible content expanded from 444 px to the expected 1348 px after accounting for the application's outer padding.

Validation

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test (149 tests passed)

No public API changes are introduced.

Copilot AI lite review requested due to automatic review settings August 20, 2026 16:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@geom3trik
geom3trik requested a lite review from Copilot August 20, 2026 16:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/layout.rs:81

  • same_axis_direction() implicitly defines axis orientation as “Column vs everything else”. That matches the mapping used in Node::layout and several match LayoutType::Row | LayoutType::Overlay | LayoutType::Grid => ... blocks, but it conflicts with LayoutType::select* in src/types.rs which currently groups Grid with Column (types.rs:24-27). Having multiple, inconsistent sources of truth for axis grouping makes future fixes risky (e.g., grid sizing/min/max selection can diverge from axis-conversion logic).

Consider consolidating the axis-orientation definition onto LayoutType (e.g., is_horizontal_main_axis()), and have both same_axis_direction() and LayoutType::select* use that single helper (or update select* to match the intended Grid grouping).

#[inline]
fn same_axis_direction(a: LayoutType, b: LayoutType) -> bool {
    matches!(a, LayoutType::Column) == matches!(b, LayoutType::Column)
}

@ExtraBinoss
ExtraBinoss force-pushed the fix/overlay-row-axis branch from 807d9d7 to b96f294 Compare August 20, 2026 16:13
@ExtraBinoss ExtraBinoss changed the title Fix axis conversion between overlay, row, and grid layouts Fix axis conversion between horizontal layout types Aug 20, 2026
@ExtraBinoss
ExtraBinoss force-pushed the fix/overlay-row-axis branch from b96f294 to 65c5285 Compare August 20, 2026 16:15
@geom3trik
geom3trik requested a balanced review from Copilot August 20, 2026 17:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/layout.rs:1443

  • The preceding comment still says that every differing LayoutType swaps axes, which is the assumption this change removes. It now contradicts the predicate and would mislead future edits; describe the horizontal-versus-vertical transition instead.
    let (mut parent_main, mut parent_cross) = if same_axis_direction(parent_layout_type, layout_type) {

@geom3trik
geom3trik merged commit 2c09be2 into vizia:main Aug 20, 2026
4 checks passed
@ExtraBinoss
ExtraBinoss deleted the fix/overlay-row-axis branch August 20, 2026 17:59
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.

3 participants