emilk / egui

egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native
https://www.egui.rs/
Apache License 2.0
22.14k stars 1.6k forks source link

API discrepancy #7

Open Uriopass opened 4 years ago

Uriopass commented 4 years ago

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 commented 4 years ago

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:

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.