I have a listbox, where on the first column it contains a text field with a button.
I have this global pointer to a nana listBox:
listbox* listBox = nullptr;
I have this class retrieved from here:
#include <nana/gui.hpp>
#include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/button.hpp>
#include <nana/gui/widgets/listbox.hpp>
#include <nana/gui/widgets/textbox.hpp>
#include <nana/gui/wvl.hpp>
#include <nana/system/platform.hpp>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <thread>
#include <Windows.h>
using namespace nana;
//Creates a textbox and button
//textbox shows the value of the sub item
//button is used to delete the item.
class inline_widget : public listbox::inline_notifier_interface
{
private:
//Creates inline widget
//listbox calls this method to create the widget
//The position and size of widget can be ignored in this process
virtual void create(window wd) override
{
//Create listbox
txt_.create(wd);
txt_.events().click([this]
{
//Select the item when clicks the textbox
indicator_->selected(pos_);
});
txt_.events().mouse_move([this]
{
//Highlight the item when hovers the textbox
indicator_->hovered(pos_);
});
txt_.events().key_char([this](const arg_keyboard& arg)
{
if (arg.key == keyboard::enter)
{
//Modify the item when enter is pressed
arg.ignore = true;
indicator_->modify(pos_, txt_.caption());
}
});
//Or modify the item when typing
txt_.events().text_changed([this]()
{
indicator_->modify(pos_, txt_.caption());
});
//Create button
btn_.create(wd);
btn_.caption("Start");
btn_.enabled(false);
btn_.events().click([this]
{
//Delete the item when button is clicked
auto & lsbox = dynamic_cast<listbox&>(indicator_->host());
//buttonPressed(btn_, pos_.item);
});
btn_.events().mouse_move([this]
{
//Highlight the item when hovers the button
indicator_->hovered(pos_);
});
}
//Activates the inline widget, bound to a certain item of the listbox
//The inline_indicator is an object to operate the listbox item,
//pos is an index object refers to the item of listbox
virtual void activate(inline_indicator& ind, index_type pos)
{
indicator_ = &ind;
pos_ = pos;
}
void notify_status(status_type status, bool status_on) override
{
//Sets focus for the textbox when the item is selected
if ((status_type::selecting == status) && status_on)
txt_.focus();
}
//Sets the inline widget size
//dimension represents the max size can be set
//The coordinate of inline widget is a logical coordinate to the sub item of listbox
void resize(const size& dimension) override
{
auto sz = dimension;
sz.width -= 50;
txt_.size(sz);
rectangle r(sz.width + 5, 0, 45, sz.height);
btn_.move(r);
}
//Sets the value of inline widget with the value of the sub item
virtual void set(const value_type& value)
{
//Avoid emitting text_changed to set caption again, otherwise it
//causes infinite recursion.
if (txt_.caption() != value)
txt_.caption(value);
}
//Determines whether to draw the value of sub item
//e.g, when the inline widgets covers the whole background of the sub item,
//it should return false to avoid listbox useless drawing
bool whether_to_draw() const override
{
return false;
}
private:
inline_indicator * indicator_{ nullptr };
index_type pos_;
textbox txt_;
button btn_;
};
This is my thread:
void theThread()
{
while (1)
{
//How can I access a button on index 0 from my listbox?
button* mybutton = listBox.at(0). ... ? -->HOW CAN I DO THIS?
mybutton->caption("I did it!!");
Sleep(1000);
}
}
And my main() function:
void main()
{
using namespace nana;
form fm(nana::API::make_center(750, 500), appear::decorate<appear::taskbar>());
listbox lsbox(fm, rectangle{ 10, 50, 700, 200 });
listBox = &lsbox;
//Create columns
lsbox.append_header("Col1");
lsbox.append_header("Col2");
lsbox.append_header("Col3");
lsbox.append_header("Col4");
lsbox.append_header("Col5");
lsbox.at(0).append({ "text1", "text2", "text3", "text4", "text5" });
lsbox.at(0).append({ "text1", "text2", "text3", "text4", "text5" });
lsbox.at(0).append({ "text1", "text2", "text3", "text4", "text5" });
lsbox.column_at(0).width(200);
lsbox.at(0).inline_factory(0, pat::make_factory<inline_widget>());
fm.show();
std::thread myThread(theThread);
exec();
myThread.join();
}
Question:
How can I access a button on index 0 that is inside a listbox, from my global listbox* pointer?
You are trying to make a complicated use of the most complicated feature of
nana::listbox(or in the Wiki), the most complicated widget in Nana.As I understand it, you do not directly "attach" an inline widget to each item in the list. Instead, the list itself generates a limited number of widgets and in each moment "inlines" one of those widgets to each and only to each of the visible items. In order to do that the list need to know how to create the widgets and how to "update" it for each item, as well as how the widget responds to the different possibles events, and how to update back the corresponding item.
This is achieved by attaching to one column of one of the categories of the list a "factory" of objects that implement the virtual interface
listbox::inline_notifier_interface. This is where you use the function of the listbox category:This explain why there is not a direct way to access the inline widgets. Maybe it is possible to implement a new interface function in the listbox for that - we will try. I have seem there is a private function
inline_pane * _m_get_inline_pane(const category_t& cat, std::size_t column_pos) constthat return ainline_panethat in turn contains astd::unique_ptr<inline_notifier_interface> inline_ptr;that one can test if empty and which one can use to refer your button. Until now, the expected way to affect the inlined widget is to change the conten of the corresponding items and to useinline_notifier_interfaceto reflect that change.As for your workaround of saving a reference to the button at the moment of creation into a global vector, you may prefer to have a global vector of
inline_widgetbecause it includes anindex_type pos_;that you could use to search that vector for an element that is currently linked to the item of interest. Of course, you will have a hard time to ensure that the vector points to live objects.You may need to note, that the way to access an
item_proxyis by usinglsbox.at(0).at(item_number), orlsbox.at(index_pair(0,item_number)).