Lua GUI2: A few additions
- Support for multimenu buttons - Support for selecting multiple items in listboxes and stacked widgets GUI2 C++ API: - Documentation fixups - Function to test if a layer of a stacked_widget is selected - Function to test if a row of a listbox is selected - listbox::select_row now returns false if it failed to select/deselect anything - Functions to count and select options of a multimenu_button - multimenu_button now always has keep_open, so the function to set it is removed - multimenu_button now assumes every option has a toggle
This commit is contained in:
parent
3c5a9aa57c
commit
1954bb67b4
9 changed files with 205 additions and 31 deletions
|
@ -368,7 +368,6 @@ void addon_manager::pre_show(window& window)
|
|||
}
|
||||
|
||||
type_filter.set_values(type_filter_entries);
|
||||
type_filter.set_keep_open(true);
|
||||
type_filter.set_callback_toggle_state_change(std::bind(&addon_manager::apply_filters, this, std::ref(window)));
|
||||
|
||||
button& url_go_button = find_widget<button>(&window, "url_go", false);
|
||||
|
|
|
@ -708,7 +708,6 @@ void preferences_dialog::post_build(window& window)
|
|||
multimenu_button& hotkey_menu = find_widget<multimenu_button>(&window, "hotkey_category_menu", false);
|
||||
|
||||
hotkey_menu.set_values(hotkey_category_entries);
|
||||
hotkey_menu.set_keep_open(true);
|
||||
hotkey_menu.set_callback_toggle_state_change(std::bind(&preferences_dialog::hotkey_type_filter_callback, this, std::ref(window)));
|
||||
|
||||
listbox& hotkey_list = setup_hotkey_list(window);
|
||||
|
|
|
@ -254,9 +254,17 @@ bool listbox::select_row(const unsigned row, const bool select)
|
|||
{
|
||||
assert(generator_);
|
||||
|
||||
int before = generator_->get_selected_item_count();
|
||||
generator_->select_item(row, select);
|
||||
|
||||
return true; // FIXME test what result should have been!!!
|
||||
return before != generator_->get_selected_item_count();
|
||||
}
|
||||
|
||||
bool listbox::row_selected(const unsigned row)
|
||||
{
|
||||
assert(generator_);
|
||||
|
||||
return generator_->is_selected(row);
|
||||
}
|
||||
|
||||
int listbox::get_selected_row() const
|
||||
|
|
|
@ -177,18 +177,25 @@ public:
|
|||
grid* get_row_grid(const unsigned row);
|
||||
|
||||
/**
|
||||
* Selectes a row.
|
||||
* Selects a row.
|
||||
*
|
||||
* @param row The row to select.
|
||||
* @param select Select or deselect the row.
|
||||
* @returns True if the operation succeeded.
|
||||
*/
|
||||
bool select_row(const unsigned row, const bool select = true);
|
||||
|
||||
/**
|
||||
* Check if a row is selected
|
||||
* @param row The row to test
|
||||
* @returns True if it is selected.
|
||||
*/
|
||||
bool row_selected(const unsigned row);
|
||||
|
||||
/**
|
||||
* Returns the first selected row
|
||||
*
|
||||
* @returns The first selected row.
|
||||
* @retval -1 No row selected.
|
||||
* @returns The first selected row, or -1 if no row is selected.
|
||||
*/
|
||||
int get_selected_row() const;
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ multimenu_button::multimenu_button()
|
|||
, retval_(0)
|
||||
, values_()
|
||||
, toggle_states_()
|
||||
, keep_open_(false)
|
||||
, droplist_(nullptr)
|
||||
{
|
||||
values_.emplace_back(config_of("label", this->get_label()));
|
||||
|
@ -140,7 +139,7 @@ void multimenu_button::signal_handler_left_button_click(const event::ui_event ev
|
|||
sound::play_UI_sound(settings::sound_button_click);
|
||||
|
||||
// If a button has a retval do the default handling.
|
||||
dialogs::drop_down_menu droplist(this->get_rectangle(), this->values_, -1, this->get_use_markup(), this->keep_open_,
|
||||
dialogs::drop_down_menu droplist(this->get_rectangle(), this->values_, -1, this->get_use_markup(), true,
|
||||
std::bind(&multimenu_button::toggle_state_changed, this));
|
||||
|
||||
droplist_ = &droplist;
|
||||
|
@ -218,9 +217,7 @@ void multimenu_button::update_config_from_toggle_states()
|
|||
for(unsigned i = 0; i < values_.size(); i++) {
|
||||
::config& c = values_[i];
|
||||
|
||||
if(c.has_attribute("checkbox")) {
|
||||
c["checkbox"] = toggle_states_[i];
|
||||
}
|
||||
c["checkbox"] = toggle_states_[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,6 +241,26 @@ void multimenu_button::toggle_state_changed()
|
|||
}
|
||||
}
|
||||
|
||||
void multimenu_button::select_option(const unsigned option, const bool selected)
|
||||
{
|
||||
assert(option < values_.size());
|
||||
|
||||
if(option < toggle_states_.size()) {
|
||||
toggle_states_.resize(option + 1);
|
||||
}
|
||||
toggle_states_[option] = selected;
|
||||
update_config_from_toggle_states();
|
||||
update_label();
|
||||
}
|
||||
|
||||
void multimenu_button::select_options(boost::dynamic_bitset<> states)
|
||||
{
|
||||
assert(states.size() == values_.size());
|
||||
toggle_states_ = states;
|
||||
update_config_from_toggle_states();
|
||||
update_label();
|
||||
}
|
||||
|
||||
void multimenu_button::set_values(const std::vector<::config>& values)
|
||||
{
|
||||
set_is_dirty(true);
|
||||
|
|
|
@ -69,16 +69,57 @@ public:
|
|||
retval_ = retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of selected elements shown on the label.
|
||||
* If more are selected, the label will say "and N others".
|
||||
*
|
||||
* @param max The maximum number of elements to show
|
||||
*/
|
||||
void set_max_shown(const int max)
|
||||
{
|
||||
max_shown_ = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of selected elements shown on the label.
|
||||
*
|
||||
* @returns The maximum number of elements to show
|
||||
*/
|
||||
int get_max_shown()
|
||||
{
|
||||
return max_shown_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of options available in the menu
|
||||
*
|
||||
* @returns The number of options in the menu
|
||||
*/
|
||||
unsigned num_options()
|
||||
{
|
||||
return values_.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an option in the menu
|
||||
*
|
||||
* @param option The option to select
|
||||
* @param selected True to select it, or false to deselect it
|
||||
*/
|
||||
void select_option(const unsigned option, const bool selected = true);
|
||||
|
||||
/**
|
||||
* Set the options selected in the menu.
|
||||
*
|
||||
* @param mask A mask specifying which options to select and deselect
|
||||
*/
|
||||
void select_options(boost::dynamic_bitset<> states);
|
||||
|
||||
/**
|
||||
* Set the available menu options.
|
||||
*
|
||||
* @param values A list of options to show in the menu
|
||||
*/
|
||||
void set_values(const std::vector<::config>& values);
|
||||
|
||||
/**
|
||||
|
@ -89,21 +130,21 @@ public:
|
|||
callback_toggle_state_change_ = callback;
|
||||
}
|
||||
|
||||
/** Returns the value of the selected row */
|
||||
//std::string get_value_string() const;
|
||||
|
||||
/**
|
||||
* Get the current state of the menu options.
|
||||
*
|
||||
* @returns A mask specifying which options are selected
|
||||
*/
|
||||
boost::dynamic_bitset<> get_toggle_states() const
|
||||
{
|
||||
return toggle_states_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deselect all the menu options.
|
||||
*/
|
||||
void reset_toggle_states();
|
||||
|
||||
void set_keep_open(const bool keep_open)
|
||||
{
|
||||
keep_open_ = keep_open;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Possible states of the widget.
|
||||
|
@ -145,8 +186,6 @@ private:
|
|||
|
||||
boost::dynamic_bitset<> toggle_states_;
|
||||
|
||||
bool keep_open_;
|
||||
|
||||
dialogs::drop_down_menu* droplist_;
|
||||
|
||||
std::function<void(boost::dynamic_bitset<>)> callback_toggle_state_change_;
|
||||
|
|
|
@ -158,6 +158,12 @@ void stacked_widget::update_selected_layer_index(const int i)
|
|||
selected_layer_ = utils::clamp<int>(i, -1, get_layer_count() - 1);
|
||||
}
|
||||
|
||||
bool stacked_widget::layer_selected(const unsigned layer)
|
||||
{
|
||||
assert(layer < get_layer_count());
|
||||
return generator_->is_selected(layer);
|
||||
}
|
||||
|
||||
void stacked_widget::select_layer(const int layer)
|
||||
{
|
||||
update_selected_layer_index(layer);
|
||||
|
|
|
@ -62,27 +62,50 @@ public:
|
|||
*
|
||||
* If more than one but not all layers are visible, this will be the number of
|
||||
* the last one made visible.
|
||||
*
|
||||
* @returns The most recently shown layer
|
||||
*/
|
||||
int current_layer() const { return selected_layer_; }
|
||||
|
||||
/**
|
||||
* Tests if the specified layer is selected (ie, visible).
|
||||
*
|
||||
* @param layer The layer to test
|
||||
* @returns True if the specified layer is selected
|
||||
*/
|
||||
bool layer_selected(const unsigned layer);
|
||||
|
||||
/**
|
||||
* Selects and displays a particular layer.
|
||||
*
|
||||
* If layer -1 is selected, all layers will be displayed but only the
|
||||
* topmost (highest-numbered) layer will receive events.
|
||||
*
|
||||
* @param layer The layer to select
|
||||
*/
|
||||
void select_layer(const int layer);
|
||||
|
||||
/**
|
||||
* Selects and displays multiple layers based on the state of the provided dynamic_bitset.
|
||||
*
|
||||
* @param mask A mask specifying which layers to select and deselect
|
||||
*/
|
||||
void select_layers(const boost::dynamic_bitset<>& mask);
|
||||
|
||||
/**
|
||||
* Gets the total number of layers.
|
||||
*
|
||||
* @returns The total number of layers
|
||||
*/
|
||||
unsigned int get_layer_count() const;
|
||||
|
||||
/**
|
||||
* Gets the grid for a specified layer.
|
||||
* This can be used to search for widgets in a hidden layer.
|
||||
*
|
||||
* @param The layer to retrieve
|
||||
* @returns The grid for the specified layer.
|
||||
*/
|
||||
grid* get_layer_grid(unsigned int i);
|
||||
|
||||
private:
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "gui/widgets/clickable_item.hpp"
|
||||
#include "gui/widgets/styled_widget.hpp"
|
||||
#include "gui/widgets/multi_page.hpp"
|
||||
#include "gui/widgets/multimenu_button.hpp"
|
||||
#include "gui/widgets/progress_bar.hpp"
|
||||
#include "gui/widgets/selectable_item.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
|
@ -428,12 +429,25 @@ int intf_set_dialog_value(lua_State* L)
|
|||
if(gui2::listbox* list = dynamic_cast<gui2::listbox*>(w))
|
||||
#endif
|
||||
{
|
||||
int v = luaL_checkinteger(L, 1);
|
||||
int n = list->get_item_count();
|
||||
if(1 <= v && v <= n) {
|
||||
list->select_row(v - 1);
|
||||
if(lua_istable(L, 1)) {
|
||||
// Do two passes in case has_minimum is true
|
||||
// Probably not the best way to do it, but should work in the majority of cases.
|
||||
std::vector<int> selected_vec = lua_check<std::vector<int>>(L, 1);
|
||||
std::set<int> selected(selected_vec.begin(), selected_vec.end());
|
||||
for(unsigned i = 0; i < list->get_item_count(); i++) {
|
||||
list->select_row(i, selected.count(i + 1));
|
||||
}
|
||||
for(unsigned i = 0; i < list->get_item_count(); i++) {
|
||||
list->select_row(i, selected.count(i + 1));
|
||||
}
|
||||
} else {
|
||||
return luaL_argerror(L, 1, "out of bounds");
|
||||
int v = luaL_checkinteger(L, 1);
|
||||
int n = list->get_item_count();
|
||||
if(1 <= v && v <= n) {
|
||||
list->select_row(v - 1);
|
||||
} else {
|
||||
return luaL_argerror(L, 1, "out of bounds");
|
||||
}
|
||||
}
|
||||
} else if(gui2::multi_page* multi_page = dynamic_cast<gui2::multi_page*>(w)) {
|
||||
int v = luaL_checkinteger(L, 1);
|
||||
|
@ -469,10 +483,21 @@ int intf_set_dialog_value(lua_State* L)
|
|||
return luaL_argerror(L, 1, "out of bounds");
|
||||
}
|
||||
} else if(gui2::stacked_widget* stacked_widget = dynamic_cast<gui2::stacked_widget*>(w)) {
|
||||
const int v = luaL_checkinteger(L, 1);
|
||||
const int n = stacked_widget->get_layer_count();
|
||||
if(v >= 0 && v <= n) {
|
||||
stacked_widget->select_layer(v - 1);
|
||||
if(lua_istable(L, 1)) {
|
||||
boost::dynamic_bitset<> states;
|
||||
states.resize(stacked_widget->get_layer_count());
|
||||
for(unsigned i : lua_check<std::vector<unsigned>>(L, 1)) {
|
||||
if(i > 0 && i <= stacked_widget->get_layer_count()) {
|
||||
states[i] = true;
|
||||
}
|
||||
}
|
||||
stacked_widget->select_layers(states);
|
||||
} else {
|
||||
const int v = luaL_checkinteger(L, 1);
|
||||
const int n = stacked_widget->get_layer_count();
|
||||
if(v >= 0 && v <= n) {
|
||||
stacked_widget->select_layer(v - 1);
|
||||
}
|
||||
}
|
||||
} else if(gui2::unit_preview_pane* unit_preview_pane = dynamic_cast<gui2::unit_preview_pane*>(w)) {
|
||||
if(const unit_type* ut = luaW_tounittype(L, 1)) {
|
||||
|
@ -489,6 +514,25 @@ int intf_set_dialog_value(lua_State* L)
|
|||
} else {
|
||||
node->fold();
|
||||
}
|
||||
} else if(gui2::multimenu_button* menu = dynamic_cast<gui2::multimenu_button*>(w)) {
|
||||
if(lua_istable(L, 1)) {
|
||||
boost::dynamic_bitset<> states;
|
||||
states.resize(menu->num_options());
|
||||
for(unsigned i : lua_check<std::vector<unsigned>>(L, 1)) {
|
||||
if(i > 0 && i <= menu->num_options()) {
|
||||
states[i] = true;
|
||||
}
|
||||
}
|
||||
menu->select_options(states);
|
||||
} else {
|
||||
int v = luaL_checkinteger(L, 1);
|
||||
int n = menu->num_options();
|
||||
if(1 <= v && v <= n) {
|
||||
menu->select_option(v - 1);
|
||||
} else {
|
||||
return luaL_argerror(L, 1, "out of bounds");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t_string v = luaW_checktstring(L, 1);
|
||||
gui2::styled_widget* c = dynamic_cast<gui2::styled_widget*>(w);
|
||||
|
@ -509,6 +553,7 @@ int intf_set_dialog_value(lua_State* L)
|
|||
int intf_get_dialog_value(lua_State* L)
|
||||
{
|
||||
gui2::widget *w = find_widget(L, 1, true);
|
||||
int num_rets = 1;
|
||||
|
||||
#ifdef GUI2_EXPERIMENTAL_LISTBOX
|
||||
if(gui2::list_view* list = dynamic_cast<gui2::list_view*>(w))
|
||||
|
@ -517,6 +562,16 @@ int intf_get_dialog_value(lua_State* L)
|
|||
#endif
|
||||
{
|
||||
lua_pushinteger(L, list->get_selected_row() + 1);
|
||||
num_rets = 2;
|
||||
lua_newtable(L);
|
||||
int count = 0;
|
||||
for(unsigned i = 0; i < list->get_item_count(); i++) {
|
||||
if(list->row_selected(i)) {
|
||||
count++;
|
||||
lua_pushnumber(L, i + 1);
|
||||
lua_rawseti(L, -1, count);
|
||||
}
|
||||
}
|
||||
} else if(gui2::multi_page* multi_page = dynamic_cast<gui2::multi_page*>(w)) {
|
||||
lua_pushinteger(L, multi_page->get_selected_page() + 1);
|
||||
} else if(gui2::selectable_item* selectable = dynamic_cast<gui2::selectable_item*>(w)) {
|
||||
|
@ -540,11 +595,32 @@ int intf_get_dialog_value(lua_State* L)
|
|||
}
|
||||
} else if(gui2::stacked_widget* stacked_widget = dynamic_cast<gui2::stacked_widget*>(w)) {
|
||||
lua_pushinteger(L, stacked_widget->current_layer());
|
||||
num_rets = 2;
|
||||
lua_newtable(L);
|
||||
int count = 0;
|
||||
for(unsigned i = 0; i < stacked_widget->get_layer_count(); i++) {
|
||||
if(stacked_widget->layer_selected(i)) {
|
||||
count++;
|
||||
lua_pushnumber(L, i + 1);
|
||||
lua_rawseti(L, -1, count);
|
||||
}
|
||||
}
|
||||
} else if(gui2::multimenu_button* menu = dynamic_cast<gui2::multimenu_button*>(w)) {
|
||||
auto selected = menu->get_toggle_states();
|
||||
int count = 0;
|
||||
lua_newtable(L);
|
||||
for(unsigned i = 0; i < selected.size(); i++) {
|
||||
if(selected[i]) {
|
||||
count++;
|
||||
lua_pushnumber(L, i + 1);
|
||||
lua_rawseti(L, -1, count);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return luaL_argerror(L, lua_gettop(L), "unsupported widget");
|
||||
}
|
||||
|
||||
return 1;
|
||||
return num_rets;
|
||||
}
|
||||
namespace
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue