orbtk
orbtk copied to clipboard
[Proposal] Consider removing widget!() macro
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
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 {
// ...
}