Skip to content

Refactor TextBuilder initialization#916

Open
CopeFiend wants to merge 1 commit into
FyroxEngine:masterfrom
CopeFiend:refactor_text_builder
Open

Refactor TextBuilder initialization#916
CopeFiend wants to merge 1 commit into
FyroxEngine:masterfrom
CopeFiend:refactor_text_builder

Conversation

@CopeFiend
Copy link
Copy Markdown
Contributor

@CopeFiend CopeFiend commented May 6, 2026

TextBuilder can now be initialized without widget_builder, which means calls like:

TextBuilder::new()
    .with_font(font)
    .with_font_size(font_size)

are now possible.

Description

Scaffolding for #911 .

Instead carrying fields/methods that do nothing but pass data down to internal TextBuilders, builders that require a TextBuilder instance should take them as parameters instead (like WidgetBuilder), this allows caller to customize values of TextBuilder, and parent Builder to override values if necessary. For example:

Problem 1

MenuItemBuilder::new(widget_builder)
    .with_font(font)
    .with_font_size(font_size)
    // What if caller wants to change Text::WrapMode?
    // MenuItemBuilder must now implement with_wrap()
    .build(ctx)

MenuItemBuilder {
    // ...
    pub font: FontResource, // Only exists to be passed down to TextBuilder
    pub font_size: StyledProperty<f32>, // Only exists to be passed down to TextBuilder
    // Need to implement wrap_mode: WrapMode
}

Problem 2

MenuItemBuilder::new(widget_builder)
    // What if caller does not want to define WidgetBuilder values?
    .with_text_builder(
        TextBuilder::new(widget_builder)
    )
    .build(ctx)

impl MenuItemBuilder {
    pub fn build(self, ctx: &mut BuildContext) -> Handle<MenuItem> {
        // No way to override WidgetBuilder
        self.text_builder
            .with_font(self.font)
            .with_font_size(self.font_size)
            .build()
    }    
}

Solution

MenuItemBuilder::new(widget_builder)
    .with_text_builder(
        // Anything a TextBuilder can have, the caller can add
        TextBuilder::new()
            .with_font(self.font)
            .with_font_size(self.font_size)
    )
    .build(ctx)

MenuItemBuilder {
    // ...
    // No need to carry transient data
   pub text_builder: Option<TextBuilder>,
}

impl MenuItemBuilder {
    pub fn build(self, ctx: &mut BuildContext) -> Handle<MenuItem> {
        self.text_builder.unwrap_or_default()
            // Builders can inject WidgetBuilder of their own
            .with_widget_builder(
                WidgetBuilder::new().with_thickness::left(2.0)
            )
            .build()
    }
}

This allows a higher degree of flexibility between caller and implementation.

Review Guidance

  • No change in project functionality.
  • All instances of TextBuilder::new(widget_builder) are now TextBuilder::new().with_widget_builder(widget_builder)
  • All instances of TextBuilder::new(WidgetBuilder::new()) are now TextBuilder::new()
  • TextBuilder::widget_builder is now an Option<WidgetBuilder> type (default: None)
  • In TextBuilder::build(), if widget_builder is None, use WidgetBuilder::new() instead.

Screenshots/GIFs

N/A

Checklist

  • My code follows the project's code style guidelines
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes don't generate new warnings or errors
  • No unsafe code introduced (or if introduced, thoroughly justified and documented)

TextBuilder can now be initialized without `widget_builder` which means calls like:
```rust
TextBuilder::new()
    .with_font(font)
    .with_font_size(font_size)
```
are now possible
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.

1 participant