Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API discrepancy #7

Open
Uriopass opened this issue Jun 27, 2020 · 1 comment
Open

API discrepancy #7

Uriopass opened this issue Jun 27, 2020 · 1 comment
Labels
design Some architectual design work needed

Comments

@Uriopass
Copy link
Contributor

Uriopass commented Jun 27, 2020

With imgui-rs, the API is pretty much the same for everything.
WidgetType::new().param(args).build(&ui, || closure executed if widget is open for example for windows or buttons)
(Actually, that's not entirely true, small widgets use ifs but their API is moving toward this version by version)

However while looking through egui's source code, I've seen 4 ways the API is declared.
menu does everything in the constructor:
menu::menu(ui, "Windows", |ui| { ... })

Button uses ifs and ui.add:
if ui.add(Button::new("Clear memory")).clicked { ... }

Windows looks a bit like imgui:
Window::new("Examples").show(ctx, |ui| { ... })

collapsing comes directly from the ui object:
ui.collapsing("About Egui", |ui| { ... })

4 different ways of doing control flow for the same idea, which makes it a bit awkward to use.

PS: I'm doing a lot of issues but it's because I'm seriously considering the crate for my project and there's a few quirks before I'm thinking of moving to it. I absolutely admire the amount of work you've put into it !

@emilk
Copy link
Owner

emilk commented Jun 29, 2020

You are right in pointing this out, and I haven't quite converged on a final design here, but there is actually some method to the madness.

There are two fundamental categories in Egui:

  • Widgets: buttons, sliders, etc. You use a builder pattern to construct them, and then you add them to a ui, e.g. ui.add(Label::new("Hello world")).

  • Containers: things that wrap code that adds widgets. Examples are ScrollArea, Resize, Frame, CollapsingHeader and Window (which is a wrapper around the four previous ones). Containers need to execute some custom code to add the contents. They follow the form Container::new(...).builder(...).show(ui, |ui| {...})

Since you never run any custom closure for e.g. Label, there makes no sense to unify Widgets and Containers. So that covers your Button and Window examples.

As for ui.collapsing: this is part of a few shortcut functions. Others include ui.button("Click me"), ui.label("Hello world"), ui.checkbox(...) and ui.radio(...). It is a bit inconsistent, but it is so much nicer to write if ui.button("OK").clicked than ui.add(Button::new("OK")).clicked. If Rust supported default, named arguments, this is the way I would design all widgets (instead of using the rather verbose builder pattern).

As for Menu: that was something I threw together pretty quickly. It should probably be refactored into a Container.

@emilk emilk added the design Some architectual design work needed label Sep 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design Some architectual design work needed
Projects
None yet
Development

No branches or pull requests

2 participants