alecmus / lecui

lecui user interface library, for rapid gui application development in C++ on Windows
MIT License
13 stars 5 forks source link

Simplify adding widget to a pane #9

Closed JamesBremner closed 3 years ago

JamesBremner commented 3 years ago

To add a widget to a pane we need to pass a reference to the pane's page as a parameter to the widget's builder.

Why?

Suggestion: Simply pass a reference to the pane, let the widget's builder call the get() method

Instead of

lecui::widgets::label_builder label(pane_one.get(), "my_label");

allow

lecui::widgets::label_builder label(pane_one, "my_label");

alecmus commented 3 years ago

Why?

The reason is that we didn't want builders knowing anything about each other. In the interface, containers don't know about widgets, and widgets don't know specific containers, they only know about a page. All containers as different as they are have a page whose reference we then fetch using .get()).

While it is certainly possible to allow

lecui::widgets::label_builder label(pane_one, "my_label");

this would mean we'd have to allow the same for all other containers since pane_one in this code is actually a builder. The result is that all widgets would know about all container builders and everything gets entangled and we thought this would lead to a more complicated app.

So while it is certainly annoying to call .get() we thought it's a smaller price to pay than to have everything coupled.

Then again, the example code could use some improvement, because calling the builder pane_one is a bit dubious. Perhaps we can improve the example code to something like this:

// add a pane to the "home page"
lecui::containers::pane_builder pane_one_builder(home, "pane_one");
pane_one_builder().rect().width(300.f).height(300.f);

auto& pane_one = pane_one_builder.get();

// add label to "pane_one"
auto& label = lecui::widgets::label_builder(pane_one, "my_label")();
label
    .text("This is a simple label and it's in a pane and we're going to make it long deliberately")
    .rect()
    .width(pane_one.size().get_width())
    .height(20.f);

What do you think?

alecmus commented 3 years ago

Thank you for the suggestion. We are working on hiding the builders entirely and this will simplify the process as you suggested.

alecmus commented 3 years ago

Suggestion: Simply pass a reference to the pane

This has since been implemented here 2544ae0d29f57a48a81d5ae53b0a05e873d34883. Thank you for the suggestion.

For example, the following code:

auto& home = _page_man.add("home");

auto& pane = containers::pane::add(home);
pane.rect().left(10.f).top(10.f).width(home.size().get_width() - 20.f).height(150.f);

auto& slider = widgets::slider::add(pane);
slider
    .value(68.f)
    .events().slider = [this](float value) { message("Value set to " + std::to_string(value)); };

auto& label = widgets::label::add(pane);
label
    .text("<span style='color: rgb(0, 150, 0); font-family: Freehand521 BT;"
        "font-size: 14pt;'>Slider</span> widget example")
    .rect().height(30.f).snap_to(slider.rect(), rect::snap_type::bottom, 10.f);

Produces this:

screenshot

The lines of interest here are the following:

auto& pane = containers::pane::add(home);
...
auto& slider = widgets::slider::add(pane);
auto& label = widgets::label::add(pane);