orbtk icon indicating copy to clipboard operation
orbtk copied to clipboard

[Proposal] Consider removing widget!() macro

Open kivimango opened this issue 4 years ago • 1 comments

Context

Consider removing the widget!() macro in the next release.

Problem description & Solution

Pros:

  • Improved build times
  • Less bloated binary
  • Simpler widget creation
  • Generic widgets now could be created (ListView<T>, TableView<T>), see https://github.com/redox-os/orbtk/issues/322
  • no inherited properties from the widget!() macro: widgets could be defined with components only that they use

Cons:

  • More boilerplate code
  • components registration in the build() method has to be done by programmatically
  • creation of custom widgets may be more confusing to new developers -> need to be documented with examples

The structs would serve as a builder, just like now but without a macro call. Probably the Template trait could be removed that too, but it would need to refactor the components/properties.

Examples and MockUps

For instance, the TextBlock could be defined and used as:

pub struct TextComponent {
    text: String
}

pub struct TextBlock {}
impl TextBlock {
     pub fn new(text: String) -> TextBlockBuilder {
        TextBlockBuilder::new(text)
    }
}

pub struct TextBlockBuilder {
    text: String
    
}
impl TextBlockBuilder {
    pub fn new(text: String) -> Self {
        self.text = text;
        self
    }
    
    pub fn build(bctx: &mut BuildContext) -> Entity {
        // create entity, then register its components with world
        let entity = bctx.create_entity();
        let text_component = TextComponent { text: self.text.clone() };
        bctx.register_component(entity, text_component);
        entity
    }
}

TextBlock::new("Sample text").build(bctx);

update: added cons

kivimango avatar Apr 11 '21 18:04 kivimango

Out of interest, would the usage of #[derive(...)] be a better fit than widget!()? At least from my rudimentary understanding of macros, it would function as a good alternative. It would probably solve the generic widgets problem and would be more familiar to most rust developers (I was very confused about the widgets macro when I first saw it). However, it would probably increase build times a bit and would have the same amount of bloat.

Mockup

#[derive(Debug, Clone, Default, AsAny)]
pub struct TextBlockState;

impl State for TextBlockState {
    // ...
}

#[derive(Widget)]
#[state(TextBlockState)] // My preferred solution for state, more complex to implement
struct TextBlock {
    // Another solution for state, although less clear to the reader
    #[state]
    state: TextBlockState,

    // Whatever else: ... 
}

impl Template for TextBlock {
    // ...
}

Docs

trickypr avatar Jan 01 '22 07:01 trickypr