Skip to content

Chaining transform methods overrides instead of composing #893

Description

@tilucasoli

Description

When chaining multiple transform methods on BoxStyler (e.g., scale() then translate()), the last transform completely replaces the previous one instead of composing them.

Steps to Reproduce

final style = BoxStyler()
    .scale(1)
    .translate(0, 10);

Box(style: style, child: child);

Expected Behavior

Both transforms should be applied: the box should be scaled and translated. The resulting Matrix4 should be the composition (multiplication) of both transform matrices.

Actual Behavior

Only the last transform (translate) is applied. The scale is silently discarded.

Root Cause

Each transform method (defined in TransformStyleMixin) calls transform(matrix) which creates a new BoxStyler with that single Matrix4 and merges it. During merge, Prop.mergeProp() correctly accumulates both Matrix4 sources. However, during resolution in Prop.resolveProp(), because Matrix4 is not a Mix type, it falls into the replacement strategy (resolvedValue = values.last) instead of composing (multiplying) the matrices.

Key code path:

  • TransformStyleMixin.scale() / .translate()transform(Matrix4) → creates new styler and merges
  • Prop.mergeProp() accumulates sources: [scaleMatrix, translateMatrix]
  • Prop.resolveProp() resolves with values.last → only translateMatrix is returned

Affected Methods

All transform helpers in TransformStyleMixin are affected when chained together:

  • scale()
  • translate()
  • rotate()
  • skew()

Any combination of two or more of these will result in only the last one being applied.

Possible Solution

Stop using Container's transform property for these operations. Instead, each transform method (scale, translate, rotate, skew) should use wrap() behind the scenes to apply the respective ModifierMix. This way, each chained call adds its own independent Modifierwidget in the widget tree, so they naturally compose without needing Matrix4 multiplication logic in theProp` resolution system.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions