GUI2/Drop Down Menu: handle toggle callbacks using the event system

This fires a NOTIFIED_MOFIDIED event in the parent widget when the toggle state changes instead of manually
passing a callback in as a ctor parameter. The only widget which handled this was the multimenu_button, and
that did some stuff, then fired off a NOTIFY_MODIFIED event of its own. This change basically just installs
a handler of its own for the NOTIFY_MODIFIED event, which should still allow any other dialogs to add their
own handlers if necessary.

This also adds a second constructor that takes the parent widget and pulls the rectangle and markup settings
from it rather than having them passed in manually. The ctor that takes them is retained for the cases where
the menu needs to be manually invoked without a parent widget.
This commit is contained in:
Charles Dang 2020-11-27 14:07:06 +11:00
parent cbb98cea26
commit 6097948e9b
5 changed files with 58 additions and 37 deletions

View file

@ -15,13 +15,16 @@
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "gui/dialogs/drop_down_menu.hpp"
#include "gui/widgets/listbox.hpp"
#include "gui/auxiliary/find_widget.hpp"
#include "gui/core/event/dispatcher.hpp"
#include "gui/dialogs/modal_dialog.hpp"
#include "gui/widgets/image.hpp"
#include "gui/widgets/integer_selector.hpp"
#include "gui/widgets/listbox.hpp"
#include "gui/widgets/scrollbar.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/styled_widget.hpp"
#include "gui/widgets/toggle_button.hpp"
#include "gui/widgets/toggle_panel.hpp"
#include "gui/widgets/window.hpp"
@ -80,6 +83,30 @@ namespace
}
}
drop_down_menu::drop_down_menu(styled_widget* parent, const std::vector<config>& items, int selected_item, bool keep_open)
: parent_(parent)
, items_(items.begin(), items.end())
, button_pos_(parent->get_rectangle())
, selected_item_(selected_item)
, use_markup_(parent->get_use_markup())
, keep_open_(keep_open)
, mouse_down_happened_(false)
{
set_restore(true);
}
drop_down_menu::drop_down_menu(SDL_Rect button_pos, const std::vector<config>& items, int selected_item, bool use_markup, bool keep_open)
: parent_(nullptr)
, items_(items.begin(), items.end())
, button_pos_(button_pos)
, selected_item_(selected_item)
, use_markup_(use_markup)
, keep_open_(keep_open)
, mouse_down_happened_(false)
{
set_restore(true);
}
void drop_down_menu::mouse_up_callback(bool&, bool&, const point& coordinate) const
{
if(!mouse_down_happened_) {
@ -174,8 +201,11 @@ void drop_down_menu::pre_show(window& window)
checkbox->set_id("checkbox");
checkbox->set_value_bool(*entry.checkbox);
if(callback_toggle_state_change_ != nullptr) {
connect_signal_notify_modified(*checkbox, std::bind(callback_toggle_state_change_));
// Fire a NOTIFIED_MODIFIED event in the parent widget when the toggle state changes
if(parent_) {
connect_signal_notify_modified(*checkbox, std::bind([this]() {
parent_->fire(event::NOTIFY_MODIFIED, *parent_, nullptr);
}));
}
mi_grid.swap_child("icon", checkbox, false);

View file

@ -26,27 +26,19 @@ class config;
namespace gui2
{
class styled_widget;
namespace dialogs
{
/** Used by the menu_button widget. */
class drop_down_menu : public modal_dialog
{
public:
drop_down_menu(SDL_Rect button_pos, const std::vector<config>& items, int selected_item, bool use_markup, bool keep_open, std::function<void()> callback_toggle_state_change = nullptr)
: items_()
, button_pos_(button_pos)
, selected_item_(selected_item)
, use_markup_(use_markup)
, keep_open_(keep_open)
, mouse_down_happened_(false)
, callback_toggle_state_change_(callback_toggle_state_change)
{
set_restore(true);
/** Menu was invoked from a widget (currently a [multi]menu_button). Its position and markup settings will be derived from there. */
drop_down_menu(styled_widget* parent, const std::vector<config>& items, int selected_item, bool keep_open);
for(const config& cfg : items) {
items_.emplace_back(cfg);
}
}
/** Menu was invoked manually. Position and markup settings must be provided here. */
drop_down_menu(SDL_Rect button_pos, const std::vector<config>& items, int selected_item, bool use_markup, bool keep_open);
int selected_item() const
{
@ -81,6 +73,9 @@ private:
t_string tooltip;
};
/** The widget that invoked this dialog, if applicable. */
styled_widget* parent_;
/** Configuration of each row. */
std::vector<entry_data> items_;
@ -107,12 +102,6 @@ private:
* */
bool mouse_down_happened_;
/**
* If toggle buttons are used, this callback is called whenever the state of any toggle
* button changes.
*/
std::function<void()> callback_toggle_state_change_;
/** Inherited from modal_dialog, implemented by REGISTER_DIALOG. */
virtual const std::string& window_id() const override;

View file

@ -141,8 +141,7 @@ void menu_button::signal_handler_left_button_click(const event::ui_event event,
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_, this->selected_, this->get_use_markup(), this->keep_open_,
nullptr);
dialogs::drop_down_menu droplist(this, values_, selected_, keep_open_);
if(droplist.show()) {
const int selected = droplist.selected_item();

View file

@ -50,16 +50,21 @@ multimenu_button::multimenu_button(const implementation::builder_multimenu_butto
values_.emplace_back("label", this->get_label());
connect_signal<event::MOUSE_ENTER>(
std::bind(&multimenu_button::signal_handler_mouse_enter, this, _2, _3));
std::bind(&multimenu_button::signal_handler_mouse_enter, this, _2, _3));
connect_signal<event::MOUSE_LEAVE>(
std::bind(&multimenu_button::signal_handler_mouse_leave, this, _2, _3));
std::bind(&multimenu_button::signal_handler_mouse_leave, this, _2, _3));
connect_signal<event::LEFT_BUTTON_DOWN>(std::bind(
&multimenu_button::signal_handler_left_button_down, this, _2, _3));
connect_signal<event::LEFT_BUTTON_DOWN>(
std::bind(&multimenu_button::signal_handler_left_button_down, this, _2, _3));
connect_signal<event::LEFT_BUTTON_UP>(
std::bind(&multimenu_button::signal_handler_left_button_up, this, _2, _3));
connect_signal<event::LEFT_BUTTON_CLICK>(std::bind(
&multimenu_button::signal_handler_left_button_click, this, _2, _3));
std::bind(&multimenu_button::signal_handler_left_button_up, this, _2, _3));
connect_signal<event::LEFT_BUTTON_CLICK>(
std::bind(&multimenu_button::signal_handler_left_button_click, this, _2, _3));
// TODO: might need to position this differently in the queue if it's called after
// dialog-specific callbacks.
connect_signal<event::NOTIFY_MODIFIED>(
std::bind(&multimenu_button::signal_handler_notify_changed, this));
}
void multimenu_button::set_active(const bool active)
@ -132,8 +137,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(), true,
std::bind(&multimenu_button::toggle_state_changed, this));
dialogs::drop_down_menu droplist(this, values_, -1, true);
droplist_ = &droplist;
droplist.show();
@ -191,12 +195,11 @@ void multimenu_button::reset_toggle_states()
update_label();
}
void multimenu_button::toggle_state_changed()
void multimenu_button::signal_handler_notify_changed()
{
assert(droplist_ != nullptr);
toggle_states_ = droplist_->get_toggle_states();
fire(event::NOTIFY_MODIFIED, *this, nullptr);
update_label();
}

View file

@ -181,7 +181,7 @@ private:
void signal_handler_left_button_click(const event::ui_event event, bool& handled);
void toggle_state_changed();
void signal_handler_notify_changed();
};
// }---------- DEFINITION ---------{