Menu

Preview of Listbox Model

The listbox model is a new feature which will be introduced into Nana 1.4. The listbox model is to use an existing STL container and adopt the container as the storage for a listbox category.

//Definition of a person
struct person
{
    std::string name;
    unsigned age;
    bool gender;
};

//A container stores persons
std::vector<person> persons;

//Insert 3 persons.
persons.push_back(person{"Steve", 20, true});
persons.push_back(person{"Nolan", 25, true});
persons.push_back(person{"Susan", 21, false});


//A listbox to list persons
nana::listbox lsbox(form, nana::rectangle{10, 10, 300, 200});

lsbox.append_header("name");
lsbox.append_header("age");
lsbox.append_header("gender");

//We have a container and a listbox.
//Now we need to defines two function to make the listbox 'recognize'
//the struct person.

auto value_translator = [](const std::vector<nana::listbox::cell>& cells)
{
    person p;
    p.name = cells[0].text;
    p.age = std::stoul(cells[1].text);
    p.gender = (cells[2].text == "male");
    return p;
};

auto cell_translator = [](const person& p)
{
    std::vector<nana::listbox::cell> cells;
    cells.emplace_back(p.name);
    cells.emplace_back(std::to_string(p.age));
    cells.emplace_back(p.gender ? "male" : "female");
    return cells;
};

//Everything is ready but last step
lsbox.at(0).model<std::recursive_mutex>(persons, value_translator, cell_translator);

The listbox displays container elements.

Two kinds of model

listbox defines 2 different model types.

1, Standalone model owns an internal container. It copys or moves from the actual argument container. The above example illustrates a standalone model, it copys the 'persons'.

lsbox.at(0).model<std::recursive_mutex>(std::move(persons), value_translator, cell_translator);

2, Shared model refers to the actual argument container. The following example illustrates the shared model.

lsbox.at(0).shared_model<std::recursive_mutex>(persons, value_translator, cell_translator);

lsbox.events().dbl_click([&]
{
    lsb.at(0).append({ "Who", "10000", "male" });

    auto size = persons.size(); //'persons' increases after double-click 
});

Restriction of shared model Don't emplace/insert/emplace_back/erase/remove the referred container. The behavior is unspecified otherwise. For example

lsbox.at(0).shared_model<std::recursive_mutex>(persons, value_translator, cell_translator);

lsbox.events().dbl_click([&]
{
    lsb.at(0).append({ "Who", "10000", "male" }); //It's OK

    persons.push_back(person{"David", 24, true}); //adding new elements/removing elements to shared model referred container is behavior unspecified!
});

model_guard

A model_guard is used for accessing the container of listbox model. model_guard is a RAII class that locks for atomically accessing model container.

lsbox.at(0).shared_model<std::recursive_mutex>(persons, value_translator, cell_translator);

lsbox.events().dbl_click([&]
{
    //model_guard(object mdg) will lock the scope to
    //atomically access model container.

    auto mdg = lsbox.at(0).model();

    auto & cont = mdg.container<std::vector<person>>();

    //Loop through 'persons'
    for(auto & ps : cont)
    {
        //ps.age;
    }

    //vs
    for(auto & im : lsbox.at(0))
    {
        //auto age = std::stoi(im.text(1));
    }
});

Exception

Posted by Jinhao 2016-04-02 | Draft

Anonymous
Anonymous

Add attachments
Cancel





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.