wjakob / nanogui

Minimalistic GUI library for OpenGL
Other
4.66k stars 608 forks source link

[Question] Set Textbox callback #311

Closed geolehmann closed 6 years ago

geolehmann commented 6 years ago

Hello,

I´m stuck with setting up the callback for a TextBox widget. My (incorrect) try so far was:

 TextBox  *txt = new TextBox(m_window);
 txt->setCallback( [&] () { /* some action here */; });

What am I missing? Thanks for any help!

svenevs commented 6 years ago

Hey @clehmann-geo, the callback is a little confusing for the TextBox. The callback signature is bool(const std::string &), so you need to receive a const std::string & argument, and in the body return a bool.

How you return depends on what you are using the textbox for. In some applications, you can use a regular expression to validate the input (this is how the derived types FloatBox and IntBox actually work). But some applications it may not be possible to represent valid / invalid input with a regular expression. The behavior is

  1. Manual (no regex): current text value supplied as argument to callback, return of false means don't use it (revert to previous value). Return of true says it is OK, update the UI.
  2. Automated (with regex): only if the entered text is valid will the callback be executed. In which case, you just return true.

The below code should help you figure out how it works

#include <nanogui/nanogui.h>
#include <iostream>

int main(void) {
    nanogui::init();

    {
        auto *screen = new nanogui::Screen({600, 600}, "TextBox");
        auto *window = new nanogui::Window(screen, "Window Title");

        // 1. make sure windows / wrapper widgets you create always have a layout
        window->setLayout(new nanogui::GroupLayout());
        window->center();

        new nanogui::Label(window, "Manual Verification");
        auto *textBox = new nanogui::TextBox(window, "initial value");
        // 2. if you want user input, make sure you set it to be editable
        textBox->setEditable(true);
        // 3. the callback only executes once you hit <enter>, or the textBox is
        //    no longer infocus (e.g., you click away from it)
        textBox->setCallback([](const std::string &value) {
            std::cout << "Current Manual Value: " << value << std::endl;
            // 4. return of function: true if valid, false if not.  in this example
            //    'no' is rejected.  so first type say 'yes' and hit enter.  then type
            //    'no' and hit enter.  since we return false, the text will not be
            //    updated in the UI
            if (value == "no")
                return false;
            return true;
        });

        // option 2: if you have a regular expression that represents valid input, you
        // can use that.  observe that when invalid text is typed followed by an <enter>
        // the callback will *NOT* be executed.
        new nanogui::Label(window, "Automatic Verification");
        textBox = new nanogui::TextBox(window, "initial");
        textBox->setEditable(true);
        textBox->setFormat("^[a-z]+$");// accept lower-case letters only
        textBox->setCallback([](const std::string &value) {
            std::cout << "Current Automatic Value: " << value << std::endl;
            return true;// we are verifying with the regex specified in setFormat
        });

        screen->performLayout();
        screen->setVisible(true);
        nanogui::mainloop();
    }

    nanogui::shutdown();

    return 0;
}

Let me know if that makes sense or not, I'll add it to the docs once I fix other problems going on.

geolehmann commented 6 years ago

@svenevs Many thanks for your help! I got confused by the callback signature, but with the code you provided I understand it now.