elements icon indicating copy to clipboard operation
elements copied to clipboard

Checkbox checkmark is not updated when linking controls.

Open wsberry opened this issue 5 years ago • 20 comments

I may be using the control incorrectly.

The workflow is such that when a checkbox is clicked then I would like other checkboxes to also be updated. i.e. Click checkbox A and have checkbox B reflect the same checked state as A.

Example Code:

#pragma once

#include <elements.hpp> #include <memory_resource>

namespace experimental::elements { namespace colors_rgba { constexpr auto alpha = 200; constexpr auto default_dark = cycfi::elements::rgba(32, 32, 32, alpha); constexpr auto slate_gray = cycfi::elements::rgba(112, 128, 144, alpha); constexpr auto antique_white = cycfi::elements::rgba(250, 235, 215, alpha); constexpr auto doger_blue = cycfi::elements::rgba(16, 78, 139, alpha); }

namespace colors_rgb { constexpr auto default_dark = cycfi::elements::rgb(32, 32, 32); constexpr auto slate_gray = cycfi::elements::rgb(112, 128, 144); constexpr auto antique_white = cycfi::elements::rgb(250, 235, 215); constexpr auto doger_blue = cycfi::elements::rgb(16, 78, 139); }

using check_box_t = cycfi::elements::basic_toggle_button<cycfi::elements::proxy<cycfi::elements::check_box_element, cycfi::elements::basic_button>>;

namespace grpc::controller { // TODO: Load from config file. // auto constexpr default_path = "";

  // Main window background color
  // Is it possible to effect forground colors_rgba?
  //
  auto constexpr bkd_color = elements::colors_rgba::slate_gray;

  class test_options_dialog final
  {
     const cycfi::elements::box_element background = cycfi::elements::box(bkd_color);

     elements::check_box_t check_box1 = cycfi::elements::check_box("gRPC Simulations Server");
     elements::check_box_t check_box2 = cycfi::elements::check_box("gRPC GPS Simulator");
     elements::check_box_t check_box3 = cycfi::elements::check_box("gRPC UAV Simulator");

     // This works, but the repainting of check_box1, 2, and 3 does not.
     // Therefore the user does not receive the desired feedback.
     //
     elements::check_box_t check_box_select_all = cycfi::elements::check_box("Select All");

     std::size_t uav_instances_to_create_ = 5;

     auto make_selection_menu()
     {
        return cycfi::elements::selection_menu(
           [&](std::string_view& select)
           {
              const char* count = select.data();
              uav_instances_to_create_ = std::atol(count);
           },
  {
     "5",
     "10",
     "15",
     "20",
  }

  ).first; // We return only the first, the menu. the second is a shared pointer to the label.
     }

     void run_selected_options() const
     {
        using namespace cycfi::elements;

        const auto simulations_data_bus = std::string(default_path).append("simulations_data_bus.exe");
        const auto gps_device_emulator = std::string(default_path).append("gps_device_emulator.exe");
        const auto uav_entity_simulator = std::string(default_path).append("uav_emulator.exe");

        std::string args = "-ignore";

        if (check_box1.value())
        {
           //system::process::start_process(simulations_data_bus.c_str(), args);
        }

        if (check_box2.value())
        {
           //system::process::start_process(gps_device_emulator.c_str(), args);
        }

        if (check_box3.value())
        {
           auto* uav_fmt = " -uav:\"UAV ";
           const auto end = uav_instances_to_create_;
           for (auto n = 0; n < end; ++n)
           {
              auto arg = uav_fmt + std::to_string(n).append("\"");
              //system::process::start_process(uav_entity_simulator.c_str(), arg);
           }
        }
     }

     auto options_button_layout(cycfi::elements::view& window_view)
     {
        using namespace cycfi::elements;

        auto run_options_button = button("Run Selected Options");

        run_options_button.on_click =
           [&](bool) mutable
        {
           run_selected_options();
        };

        return
           margin({ 20, 0, 20, 20 },
              vtile(
                 top_margin(20, run_options_button),
                 top_margin(10,

                    htile(
                       margin({ 0, 0, 10, 0 },
                          label("UAV Count:")
                          .text_align(canvas::right)),
                       hmin_size(30, make_selection_menu()))
                 ),
                 top_margin(10, check_box_select_all)
              )
           );
     }

     void assign_checkbox_event_handlers(cycfi::elements::view& window_view)
     {
        check_box_select_all.on_click =
           [&](bool) mutable
           {
              check_box_select_all.value(!check_box_select_all.value());

              // ' window_view.refresh(check_box1);' code is not working...
              //
              const auto update = check_box_select_all.value();

              check_box1.on_click(update);
              check_box2.on_click(update);
              check_box3.on_click(update);

              return true;
           };

        check_box1.on_click =
           [&](bool) mutable
           {
              check_box1.value(!check_box1.value());
              window_view.refresh(check_box1);
           };

        check_box2.on_click =
           [&](bool) mutable
           {
              check_box2.value(!check_box2.value());
              window_view.refresh(check_box2);
           };

        check_box3.on_click =
           [&](bool) mutable
           {
              check_box3.value(!check_box3.value());
              window_view.refresh(check_box3);
           };
     }

     auto create_view_models(cycfi::elements::view& window_view)
     {
        using namespace cycfi::elements;

        check_box1.value(false);
        check_box2.value(false);
        check_box3.value(false);

        assign_checkbox_event_handlers(window_view);

        auto  check_boxes =
           group("Components",
              margin({ 10, 10, 20, 20 },
                 top_margin(25,
                    vtile(
                       top_margin(10, align_left(check_box1)),
                       top_margin(10, align_left(check_box2)),
                       top_margin(10, align_left(check_box3))
                    )
                 )
              )
           );

        return
           vtile(
              htile(
                 options_button_layout(window_view),
                 vtile(
                    margin({ 20, 20, 20, 20 }, check_boxes)
                 )
              )
           );
     }

  public:

     auto show(const int argc = 0, char* argv[] = nullptr)
     {
        using namespace cycfi::elements;

        app app_instance(argc, argv, "gRPC - Simulations (Munitions) Data Bus", "");
        window window_model(app_instance.name());
        window_model.on_close = [&app_instance]() { app_instance.stop(); };
        view window_view(window_model);
        window_view.content(create_view_models(window_view), background);
        app_instance.run();
     }
  };
  inline int show_dialog(const int argc, char* argv[])
  {
     test_options_dialog dialog;
     dialog.show(argc, argv);
     return 0;
  }

} } // using namespace experimental::elements;

//#include "grpc-startup-controller.hh"

using namespace experimental::elements::grpc;

/**

  • \brief
  • \param argc
  • \param argv
  • \return / int main(const int argc, char argv[]) { return controller::show_dialog(argc, argv); }

Again, this is awesome work you are doing. Thanks so so much!

  • Bill Berry

wsberry avatar Jul 09 '20 21:07 wsberry

I suggest either 1) placing the controls in a composite (e.g. a pane or something) and refreshing the whole composite window_view.refresh(a_pane) or 2) simply refreshing the whole view window_view.refresh().

djowel avatar Jul 09 '20 22:07 djowel

Thanks!

I will try it out.

Bill Berry

On Thu, Jul 9, 2020 at 5:01 PM Joel de Guzman [email protected] wrote:

I suggest either 1) placing the controls in a composite (e.g. a pane or something) and refreshing the whole composite window_view.refresh(a_pane) or 2) simply refreshing the whole view window_view.refresh().

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/cycfi/elements/issues/179#issuecomment-656372043, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOKC7SW6TMGDGXCVKAOD6LR2Y42BANCNFSM4OV7VUTA .

wsberry avatar Jul 10 '20 03:07 wsberry

Feel free to ask more questions, or even suggest improvements.

djowel avatar Jul 10 '20 05:07 djowel

@wsberry were you able to solve your issue? Is it good to close this now?

djowel avatar Jul 14 '20 23:07 djowel

I was working on a presentation for work and will be trying the fix later this week.

Thanks

Bill

On Tue, Jul 14, 2020 at 6:21 PM Joel de Guzman [email protected] wrote:

@wsberry https://github.com/wsberry were you able to solve your issue? Is it good to close this now?

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/cycfi/elements/issues/179#issuecomment-658459886, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOKC7VDNFRBIQZ3DYRU4E3R3TSAJANCNFSM4OV7VUTA .

wsberry avatar Jul 15 '20 01:07 wsberry

Joel,

The following did not work:

 check_box1.on_click =
           [&](bool) mutable
        {
           check_box1.value(!check_box1.value());

           // Does not work:
              window_view.refresh();
           // also does not work
              window_view.refresh(check_box1);
        }

I did not have time to test a 'panel' since I need to look up how to use it...i.e. I was hoping to do something like this:

check_box_panel = top_margin(25, vtile( top_margin(10, align_left(check_box1)), top_margin(10, align_left(check_box2)), top_margin(10, align_left(check_box3)) ) ); The above code is not supported. I plan to take a look at this tomorrow when I have more time.

Also, I will have time to trace through the code tomorrow to see why a standard refresh won't work on the control itself. This will give me an opportunity to learn better what I am doing with the elements framework.

Thanks,

Bill Berry

On Tue, Jul 14, 2020 at 8:56 PM William Berry [email protected] wrote:

I was working on a presentation for work and will be trying the fix later this week.

Thanks

Bill

On Tue, Jul 14, 2020 at 6:21 PM Joel de Guzman [email protected] wrote:

@wsberry https://github.com/wsberry were you able to solve your issue? Is it good to close this now?

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/cycfi/elements/issues/179#issuecomment-658459886, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOKC7VDNFRBIQZ3DYRU4E3R3TSAJANCNFSM4OV7VUTA .

wsberry avatar Jul 15 '20 19:07 wsberry

Joel, The following did not work:

Hrmmm... Well, if you post an MVCE (as minimal as you can get it to be), I can try it out myself to see what's happening. The view refresh mechanism should work. The radio buttons and menus do something similar to what you are doing.

djowel avatar Jul 16 '20 00:07 djowel

@wsberry is this still an issue and will you post an MVCE if it is?

djowel avatar Aug 26 '20 07:08 djowel

Yes I had looked into and your prior suggestions did not work for me.

I am using elements to write some support tools so fixing it has been on the bottom of my list. I.e. I am tracing through the problem during some of break times.

This said I can certainly post an MVCE and will try to do so today.

Bill Berry

On Wed, Aug 26, 2020 at 2:13 AM Joel de Guzman [email protected] wrote:

@wsberry https://github.com/wsberry is this still an issue and will you post an MVCE if it is?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/cycfi/elements/issues/179#issuecomment-680703449, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOKC7U4OBAGZQBV3ZJYVYTSCSYX5ANCNFSM4OV7VUTA .

wsberry avatar Aug 26 '20 11:08 wsberry

Appreciated!

djowel avatar Aug 26 '20 13:08 djowel

Any update?

djowel avatar Sep 13 '20 12:09 djowel

Joel,

Attached is a minimal test program. I have not had the time to debug the code but will if some time frees up for me.

I did try your earlier suggestions but none of them worked.

Thanks

Bill Berry

On Sun, Sep 13, 2020 at 7:25 AM Joel de Guzman [email protected] wrote:

Any update?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/cycfi/elements/issues/179#issuecomment-691665101, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOKC7RAUFNVRCFPXS3COI3SFS22LANCNFSM4OV7VUTA .

#include #include #include <elements.hpp>

namespace colors { constexpr auto default_dark = cycfi::elements::rgba(32, 32, 32,/alpha:/155); auto constexpr bkd_color = colors::default_dark; }

// Basic check box type // using check_box_t = cycfi::elements::basic_toggle_button<cycfi::elements::proxy<cycfi::elements::check_box_element, cycfi::elements::basic_button>>;

class test_options_dialog final { const cycfi::elements::box_element background = cycfi::elements::box(colors::bkd_color); check_box_t check_box1 = cycfi::elements::check_box("A"); check_box_t check_box2 = cycfi::elements::check_box("B"); check_box_t check_box3 = cycfi::elements::check_box("C"); check_box_t check_box_select_all = cycfi::elements::check_box("Select All");

void run_selected_options() const { using namespace cycfi::elements;

  std::string args = "-ignore";

  if (check_box1.value())
  {
     std::cout << "1 selected\n";
  }

  if (check_box2.value())
  {
     std::cout << "2 selected\n";
  }

  if (check_box3.value())
  {
     std::cout << "1 selected\n";
  }

}

auto options_button_layout(cycfi::elements::view& window_view) { using namespace cycfi::elements;

  auto run_options_button = button("Run Selected Options");

  run_options_button.on_click =
     [&](bool) mutable
  {
     run_selected_options();
  };


  return
     margin({ 20, 0, 20, 20 },
        vtile(

           top_margin(20, run_options_button),
           top_margin(10, check_box_select_all)

        )

     );

}

auto create_view_models(cycfi::elements::view& window_view) { using namespace cycfi::elements;

  check_box1.value(false);
  check_box2.value(false);
  check_box3.value(false);

  // TODO: Not Working
  //
  check_box_select_all.on_click =
     [&](bool) mutable
  {
     check_box_select_all.value(!check_box_select_all.value());
     const auto update = check_box_select_all.value();

     // *** The following code is not working. The check_boxes are
     //     in a checked state, but do not reflect the state on
     //     the GUI (i.e. the box is not checked).
     //
     check_box1.on_click(update);
     check_box2.on_click(update);
     check_box3.on_click(update);

     window_view.refresh();

     return true;
  };

  check_box1.on_click =
     [&](bool) mutable
  {
     check_box1.value(!check_box1.value());
  };

  check_box2.on_click =
     [&](bool) mutable
  {
     check_box2.value(!check_box2.value());
  };

  check_box3.on_click =
     [&](bool) mutable
  {
     check_box3.value(!check_box3.value());
  };

  auto  check_boxes =
     group("Components",
        margin({ 10, 10, 20, 20 },
           top_margin(25,
              vtile(
                 top_margin(10, align_left(check_box1)),
                 top_margin(10, align_left(check_box2)),
                 top_margin(10, align_left(check_box3))
              )
           )
        )
     );

  return
     vtile(
        htile(
           options_button_layout(window_view),
           vtile(
              margin({ 20, 20, 20, 20 }, check_boxes)
           )
        )
     );

}

public:

auto show(const int argc = 0, char* argv[] = nullptr) { using namespace cycfi::elements;

  app app_instance(argc, argv, "Checkbox Tester", "anyar.research.experimental");

  window window_model(app_instance.name());

  window_model.on_close = [&app_instance]() { app_instance.stop(); };

  view window_view(window_model);

  window_view.content(
     create_view_models(window_view),
     background
  );

  app_instance.run();

} }; inline int show_dialog(const int argc, char* argv[]) { test_options_dialog dialog; dialog.show(argc, argv); return 0; }

int main(const int argc, char* argv[]) { return show_dialog(argc, argv); }

wsberry avatar Sep 14 '20 13:09 wsberry

OK, got it. Thanks for the MVCE. It really helps!

The main issue here is that: if you want an element to interact with other elements, you need to "share" it and "hold" the shared element in the composition. There are a couple of unrelated changes I made to your code which I shall explain below. Here's the correct code:

#include <string>
#include <iostream>
#include <elements.hpp>

using namespace cycfi::elements;

namespace colors
{
    constexpr auto default_dark = rgba(32, 32, 32, 255);
    auto constexpr bkd_color = ::colors::default_dark;
}

// Basic check box type
//
using check_box_t = decltype(share(check_box("name")));

class test_options_dialog final
{
    const box_element background =      box(::colors::bkd_color);
    check_box_t check_box1 =            share(check_box("A"));
    check_box_t check_box2 =            share(check_box("B"));
    check_box_t check_box3 =            share(check_box("C"));
    check_box_t check_box_select_all =  share(check_box("Select All"));

    void run_selected_options() const
    {
        std::string args = "-ignore";

        if (check_box1->value())
        {
            std::cout << "1 selected\n";
        }
        else
        {
            std::cout << "1 not selected\n";
        }

        if (check_box2->value())
        {
            std::cout << "2 selected\n";
        }
        else
        {
            std::cout << "2 not selected\n";
        }

        if (check_box3->value())
        {
            std::cout << "3 selected\n";
        }
        else
        {
            std::cout << "3 not selected\n";
        }
    }

    auto options_button_layout(view& window_view)
    {
       auto run_options_button = button("Run Selected Options");

       run_options_button.on_click =
            [&](bool) mutable
            {
                run_selected_options();
            };

       return
            margin({ 20, 0, 20, 20 },
                vtile(
                    top_margin(20, run_options_button),
                    top_margin(10, hold(check_box_select_all))
                )
            );
    }

    auto create_view_models(view& window_view)
    {
       check_box1->value(false);
       check_box2->value(false);
       check_box3->value(false);

       check_box_select_all->on_click =
            [&](bool) mutable
            {
                const auto update = check_box_select_all->value();

                check_box1->value(update);
                check_box2->value(update);
                check_box3->value(update);

                window_view.refresh();

                return true;
            };

       auto  check_boxes =
            group("Components",
                margin({ 10, 10, 20, 20 },
                    top_margin(25,
                        vtile(
                            top_margin(10, align_left(hold(check_box1))),
                            top_margin(10, align_left(hold(check_box2))),
                            top_margin(10, align_left(hold(check_box3)))
                        )
                    )
                )
            );

       return
            vtile(
                htile(
                    options_button_layout(window_view),
                    vtile(
                        margin({ 20, 20, 20, 20 }, check_boxes)
                    )
                )
            );
    }

public:

    auto show(const int argc = 0, char* argv[] = nullptr)
    {
       app app_instance(argc, argv, "Checkbox Tester", "anyar.research.experimental");
       window window_model(app_instance.name());
       window_model.on_close = [&app_instance]() { app_instance.stop(); };
       view window_view(window_model);

       window_view.content(
            create_view_models(window_view),
            background
       );

       app_instance.run();
    }
};

inline int show_dialog(const int argc, char* argv[])
{
    test_options_dialog dialog;
    dialog.show(argc, argv);
    return 0;
}

int main(const int argc, char* argv[])
{
    return show_dialog(argc, argv);
}

A couple of things:

  1. Use decltype. It will make your life so much easier. See line 15.
  2. The interacting check-boxes are "shared".
  3. The interacting elements are held ("hold"). Lines 73 and 108-110.
  4. Don't set the value via on_click. Do it via btn->value(val); line 94-96

Aside: I removed the code where you changed the value of the button in the on_click (e.g. check_box3.value(!check_box3.value());). That is not necessary and is incorrect. Another aside: A non-opaque background might be confusing (in this case) because the previous drawing state persists.

I hope this helps! This will be clarified in the documentation currently WIP.

djowel avatar Sep 15 '20 00:09 djowel

The reason why you need to "share" and "hold" interacting elements is that the elements uses value semantics everywhere. So, when you make a composition, the elements are actually copied. Therefore, if you do not share the element, it will not be the same element that is actually held in the composition. "share" and "hold" changes value semantics to reference semantics.

djowel avatar Sep 15 '20 00:09 djowel

I'll close this now. Feel free to reopen if you are not satisfied with the answer.

djowel avatar Sep 15 '20 00:09 djowel

Hmmm... actually, I'll reopen this for the sake of others who have the same problem, pending proper documentation.

djowel avatar Sep 15 '20 00:09 djowel

Thanks Joel!

This is a great help!

Thank you also for the tips, corrections, and other suggestions.

I am looking forward to getting deeper into elements.

  • Bill Berry

On Mon, Sep 14, 2020 at 7:45 PM Joel de Guzman [email protected] wrote:

OK, got it. Thanks for the MVCE. It really helps!

The main issue here is that: if you want an element to interact with other elements, you need to "share" it and "hold" the shared element in the composition. There are a couple of unrelated changes I made to your code which I shall explain below. Here's the correct code:

#include #include #include <elements.hpp> using namespace cycfi::elements; namespace colors { constexpr auto default_dark = rgba(32, 32, 32, 255); auto constexpr bkd_color = ::colors::default_dark; } // Basic check box type//using check_box_t = decltype(share(check_box("name"))); class test_options_dialog final { const box_element background = box(::colors::bkd_color); check_box_t check_box1 = share(check_box("A")); check_box_t check_box2 = share(check_box("B")); check_box_t check_box3 = share(check_box("C")); check_box_t check_box_select_all = share(check_box("Select All"));

void run_selected_options() const
{
   std::string args = "-ignore";

   if (check_box1->value())
   {
      std::cout << "1 selected\n";
   }
   else
   {
      std::cout << "1 not selected\n";
   }

   if (check_box2->value())
   {
      std::cout << "2 selected\n";
   }
   else
   {
      std::cout << "2 not selected\n";
   }

   if (check_box3->value())
   {
      std::cout << "3 selected\n";
   }
   else
   {
      std::cout << "3 not selected\n";
   }
}

auto options_button_layout(view& window_view)
{
   auto run_options_button = button("Run Selected Options");

   run_options_button.on_click =
           [&](bool) mutable
           {
               run_selected_options();
           };


   return
           margin({ 20, 0, 20, 20 },
                  vtile(

                          top_margin(20, run_options_button),
                          top_margin(10, hold(check_box_select_all))

                  )

           );
}

auto create_view_models(view& window_view)
{
   check_box1->value(false);
   check_box2->value(false);
   check_box3->value(false);

   // TODO: Not Working
   //
   check_box_select_all->on_click =
           [&](bool) mutable
           {
            //    check_box_select_all->value(!check_box_select_all->value());
               const auto update = check_box_select_all->value();

               check_box1->value(update);
               check_box2->value(update);
               check_box3->value(update);

               window_view.refresh();

               return true;
           };

   auto  check_boxes =
           group("Components",
                 margin({ 10, 10, 20, 20 },
                        top_margin(25,
                                   vtile(
                                           top_margin(10, align_left(hold(check_box1))),
                                           top_margin(10, align_left(hold(check_box2))),
                                           top_margin(10, align_left(hold(check_box3)))
                                   )
                        )
                 )
           );

   return
           vtile(
                   htile(
                           options_button_layout(window_view),
                           vtile(
                                   margin({ 20, 20, 20, 20 }, check_boxes)
                           )
                   )
           );
}

public:

auto show(const int argc = 0, char* argv[] = nullptr)
{
   app app_instance(argc, argv, "Checkbox Tester", "anyar.research.experimental");

   window window_model(app_instance.name());

   window_model.on_close = [&app_instance]() { app_instance.stop(); };

   view window_view(window_model);

   window_view.content(
           create_view_models(window_view),
           background
   );

   app_instance.run();
}

};inline int show_dialog(const int argc, char* argv[]) { test_options_dialog dialog; dialog.show(argc, argv); return 0; } int main(const int argc, char* argv[]) { return show_dialog(argc, argv); }

A couple of things:

  1. Use decltype. It will make your life so much easier. See line 15.
  2. The interacting check-boxes are "shared".
  3. The interacting elements are held ("hold"). Lines 73 and 108-110.
  4. Don't set the value via on_click. Do it via btn->value(val); line 94-96

Aside: I removed the code where you changed the value of the button in the on_click (e.g. check_box3.value(!check_box3.value());). That is not necessary and is incorrect.

I hope this helps! This will be clarified in the documentation currently WIP.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/cycfi/elements/issues/179#issuecomment-692393200, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOKC7TR2IPX7OT7IT3IUCTSF22KPANCNFSM4OV7VUTA .

wsberry avatar Sep 15 '20 03:09 wsberry

@djowel have you thought about different implementations of the event handling/bounds calculation? Something of ECS type or signal-slot? These are very far from elements implementation but I'm curious if you have considered them and if yes - what are your thoughts on them. IMO I have a feeling that ECS can have much more efficient handling (although every element would need to be connected to sort of cerntral registry - many elements require view anyway) and signal-slot can scale much better (instead of iterating over elemens, it's iterating over signals and connected slots).

Xeverous avatar Sep 15 '20 09:09 Xeverous

@djowel have you thought about different implementations of the event handling/bounds calculation? Something of ECS type or signal-slot? These are very far from elements implementation but I'm curious if you have considered them and if yes - what are your thoughts on them. IMO I have a feeling that ECS can have much more efficient handling (although every element would need to be connected to sort of cerntral registry - many elements require view anyway) and signal-slot can scale much better (instead of iterating over elemens, it's iterating over signals and connected slots).

I was inclined to flag this as OT, but I didn't do it because it is tangentially related. I'll give my reply, but I'll make it short. If you want to discuss design issues further, well, this is not the place for it. There's the discord group chat for that.

Anyway, my answer will also be irrelevant primarily because at this point, it's too late in the design cycle to change things the way they are. As I pointed out elsewhere, I am no longer inclined to entertain substantial design changes.

But answering for the sake of answering... Focusing on the on_* handlers only as relevant in this discussion, I prefer direct communication between components. Signals-and-slots has its place, for sure, but in terms of design, the analogy is a bulletin board where one posts messages and interested parties connect to be notified of such posts they are interested in. Essentially a one-to-many relationship. For elements, I prefer a one-to-one relationship, because generally that's what's happening. Moreover, direct communication via the on_* handlers does not preclude one-to-many relationships. For instance, an on_click function is generic enough and can connect to an app specific signals/slots or "event bus". It's up to you, the app designer, if you want that. There is no system-wide "way of doing things" that is forced into the user. That follows the keep-it-simple design principle.

If you are thinking about replying further, please don't. Instead, move the discussion over to the discord chat group. I do not want to veer too much from the topic.

djowel avatar Sep 15 '20 18:09 djowel

Ok, thanks for the response. This answer is enough.

Xeverous avatar Sep 15 '20 21:09 Xeverous