50 #include <boost/preprocessor/cat.hpp>
57 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
61 if(
auto window =
w.get_window()) {
62 window->invalidate_layout();
70 int n = list->get_item_count();
76 return list->get_row_grid(
i - 1);
78 int n = multi_page->get_page_count();
84 return &multi_page->page_grid(
i - 1);
89 throw std::invalid_argument(
"out of range");
93 int n = tree_view_node->count_children();
95 throw std::invalid_argument(
"out of range");
97 return &tree_view_node->get_child_at(
i - 1);
99 int n = stacked_widget->get_layer_count();
101 throw std::invalid_argument(
"out of range");
103 return stacked_widget->get_layer_grid(
i - 1);
110 return w.find(m,
false);
116 using tsetters = std::map<std::string, std::vector<std::function<bool(lua_State*,
int,
gui2::widget&,
bool)>>>;
119 template<
typename w
idget_type,
typename value_type,
typename action_type,
bool setter>
123 using map_type = std::conditional_t<setter, tsetters, tgetters>;
124 using list_type =
typename map_type::mapped_type;
125 using callback_type =
typename list_type::value_type;
130 fcn = [action = action_type()](lua_State* L,
int idx,
gui2::widget&
w,
bool nop) {
131 if(widget_type* pw =
dynamic_cast<widget_type*
>(&
w)) {
132 if(!nop) action.set(L, *pw, lua_check<value_type>(L, idx));
139 fcn = [action = action_type()](lua_State* L,
gui2::widget&
w,
bool nop) {
140 if(widget_type* pw =
dynamic_cast<widget_type*
>(&
w)) {
141 if(!nop)
lua_push(L, action.get(L, *pw));
147 list_type& list = (*map)[std::string(name_part)];
152 #define WIDGET_GETTER4(name, value_type, widgt_type, id) \
153 struct BOOST_PP_CAT(getter_, id) : public lua_getter<widgt_type, value_type> { \
154 value_type get(lua_State* L, const widgt_type& w) const override; \
156 struct BOOST_PP_CAT(getter_adder_, id) { \
157 BOOST_PP_CAT(getter_adder_, id) () \
159 register_widget_attribute<widgt_type, value_type, BOOST_PP_CAT(getter_, id), false>(name); \
162 static BOOST_PP_CAT(getter_adder_, id) BOOST_PP_CAT(getter_adder_instance_, id) ; \
163 value_type BOOST_PP_CAT(getter_, id)::get([[maybe_unused]] lua_State* L, const widgt_type& w) const
166 #define WIDGET_SETTER4(name, value_type, widgt_type, id) \
167 struct BOOST_PP_CAT(setter_, id) : public lua_setter<widgt_type, value_type> { \
168 void set(lua_State* L, widgt_type& w, const value_type& value) const override; \
170 struct BOOST_PP_CAT(setter_adder_, id) { \
171 BOOST_PP_CAT(setter_adder_, id) ()\
173 register_widget_attribute<widgt_type, value_type, BOOST_PP_CAT(setter_, id), true>(name); \
176 static BOOST_PP_CAT(setter_adder_, id) BOOST_PP_CAT(setter_adder_instance_, id); \
177 void BOOST_PP_CAT(setter_, id)::set([[maybe_unused]] lua_State* L, widgt_type& w, const value_type& value) const
185 #define WIDGET_GETTER(name, value_type, widgt_type) WIDGET_GETTER4(name, value_type, widgt_type, __LINE__)
187 #define WIDGET_SETTER(name, value_type, widgt_type) WIDGET_SETTER4(name, value_type, widgt_type, __LINE__)
194 return w.get_selected_row() + 1;
199 w.select_row(value - 1);
204 return w.get_selected_page() + 1;
209 w.select_page(value -1);
214 return w.current_layer() + 1;
219 w.select_layer(value - 1);
224 return w.get_value() + 1;
229 if(value >
int(
w.num_states())) {
230 throw std::invalid_argument(
"invalid index");
232 w.set_value(value - 1);
237 if(
w.num_states() == 2) {
238 return w.get_value_bool();
240 throw std::invalid_argument(
"invalid widget");
245 w.set_value_bool(value);
250 return w.get_value();
260 return w.get_value();
270 return w.get_best_slider_length();
276 throw std::invalid_argument(
"best_slider_length must be >= 0");
278 w.set_best_slider_length(value);
283 return w.get_maximum_value();
288 w.set_value_range(
w.get_minimum_value(), value);
293 return w.get_maximum_value_label();
298 w.set_maximum_value_label(value);
304 return w.get_minimum_value();
309 w.set_value_range(value,
w.get_maximum_value());
314 return w.get_minimum_value_label();
319 w.set_minimum_value_label(value);
325 return w.get_percentage();
330 w.set_percentage(value);
335 auto res =
w.selected_item()->describe_path();
336 for(
int& a : res) { ++a;}
342 auto res =
w.describe_path();
343 for(
int& a : res) { ++a;}
349 return !
w.get_root_node().is_folded();
355 w.get_root_node().unfold();
357 w.get_root_node().fold();
363 return !
w.is_folded();
378 w.set_display_data(*ut);
380 w.set_display_data(*u);
388 return w.get_item_count();
393 return w.get_item_count();
398 return w.get_page_count();
403 return w.get_layer_count();
414 return w.count_children();
419 return w.get_use_markup();
424 w.set_use_markup(value);
433 w.set_use_markup(
true);
439 return w.get_characters_per_line();
445 throw std::invalid_argument(
"characters_per_line must be >= 0");
447 w.set_characters_per_line(value);
453 return w.is_editable();
458 w.set_editable(value);
474 return w.get_active();
484 return w.help_message();
489 w.set_help_message(value);
494 return w.get_hint_image();
499 w.set_hint_image(value);
505 return w.get_hint_text();
510 w.set_hint_text(value);
516 return w.get_hint_image();
521 w.set_hint_image(value);
527 return w.get_hint_text();
532 w.set_hint_text(value);
538 w.set_history(value);
543 return w.get_indentation_step_size();
549 throw std::invalid_argument(
"indentation_step_size must be >= 0");
551 w.set_indentation_step_size(value);
557 return w.get_link_aware();
562 w.set_link_aware(value);
568 return w.get_link_aware();
573 w.set_link_aware(value);
579 return w.get_link_aware();
584 w.set_link_aware(value);
590 return w.get_link_aware();
595 w.set_link_aware(value);
601 return w.get_link_color().to_hex_string();
606 return w.get_link_color().to_hex_string();
611 return w.get_max_input_length();
617 throw std::invalid_argument(
"max_input_length must be >= 0");
619 w.set_max_input_length(value);
625 return w.get_max_input_length();
631 throw std::invalid_argument(
"max_input_length must be >= 0");
633 w.set_max_input_length(value);
639 return w.get_step_size();
645 throw std::invalid_argument(
"step_size must be >= 0");
647 w.set_step_size(value);
667 w.set_tooltip(value);
672 return w.get_use_tooltip_on_label_overflow();
677 w.set_use_tooltip_on_label_overflow(value);
688 w.set_can_wrap(value);
698 w.set_can_wrap(value);
704 ERR_LUA <<
"gui.widget.set_callback didn't exist";
707 lua_pushvalue(L, value.index);
714 switch(
w.get_visible()) {
734 visibility
flag = visibility::visible;
736 switch(lua_type(L, value.index)) {
739 ? visibility::visible
740 : visibility::invisible;
744 const std::string& str = lua_tostring(L, value.index);
745 if(str ==
"visible") {
746 flag = visibility::visible;
747 }
else if(str ==
"hidden") {
748 flag = visibility::hidden;
749 }
else if(str ==
"invisible") {
750 flag = visibility::invisible;
752 luaL_argerror(L, value.index,
"string must be one of: visible, hidden, invisible");
762 if(
flag == visibility::hidden) {
774 return w.get_label();
790 return sw->get_control_type();
793 return "tree_view_node";
812 ERR_LUA <<
"widget was deleted";
817 ERR_LUA <<
"cannot find window in widget callback";
827 throw std::invalid_argument(
"the widget has no window assigned");
829 lua_pushvalue(L, value.index);
839 throw std::invalid_argument(
"the widget has no window assigned");
841 lua_pushvalue(L, value.index);
853 throw std::invalid_argument(
"the widget has no window assigned");
856 throw std::invalid_argument(
"unsupported widget");
858 lua_pushvalue(L, value.index);
871 if(lua_isinteger(L, 2)) {
879 std::string_view str = lua_check<std::string_view>(L, 2);
883 for(
const auto& func : it->second) {
884 if(func(L,
w,
false)) {
889 if(
luaW_getglobal(L,
"gui",
"widget", std::string(str).c_str())) {
896 ERR_LUA <<
"invalid property of '" <<
typeid(
w).name()<<
"' widget :" << str;
897 std::string
err =
"invalid property of widget: ";
899 return luaL_argerror(L, 2,
err.c_str());
905 std::string_view str = lua_check<std::string_view>(L, 2);
910 for(
const auto& func : it->second) {
911 if(func(L, 3,
w,
false)) {
915 ERR_LUA <<
"none of "<< it->second.size() <<
" setters matched";
918 ERR_LUA <<
"unknown property id : " << str <<
" #known properties=" <<
setters.size();
921 ERR_LUA <<
"invalid modifiable property of '" <<
typeid(
w).name()<<
"' widget:" << str;
922 std::string
err =
"invalid modifiable property of widget: ";
924 return luaL_argerror(L, 2,
err.c_str());
930 std::vector<std::string> keys;
932 for(
const auto& [key, funcs] :
getters) {
933 if(key ==
"value_compat")
continue;
934 for(
const auto& func : funcs) {
935 if(func(L,
w,
true)){
942 for(
const auto& [key, funcs] :
setters) {
943 if(key ==
"value_compat")
continue;
944 if(key ==
"callback")
continue;
945 for(
const auto& func : funcs) {
946 if(func(L, 0,
w,
true)){
954 for(
auto child = iter_t(
w); !child.at_end(); child.next()) {
955 const auto& key = child->
id();
956 if(!key.empty() && key !=
w.id()) {
963 keys.insert(keys.end(), methods.begin(), methods.end());
virtual void connect_click_handler(const event::signal &signal)=0
Connects a signal handler for a 'click' event.
A rich_label takes marked up text and shows it correctly formatted and wrapped but no scrollbars are ...
Small abstract helper class.
A widget that allows the user to input text in single line.
tree_view_node & get_child_at(int index)
std::size_t count_children() const
The number of children in this widget.
base class of top level items, the only item which needs to store the final canvases to draw on.
void invalidate_layout()
Updates the size of the window.
Tmust inherit enable_lua_ptr<T>
A single unit type that the player may recruit.
This class represents a single unit of a specific type.
Contains the base iterator class for the gui2 widgets.
Standard logging facilities (interface).
bool luaW_toboolean(lua_State *L, int n)
int luaW_type_error(lua_State *L, int narg, const char *tname)
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil.
std::vector< std::string > luaW_get_attributes(lua_State *L, int idx)
This function does the actual work of grabbing all the attribute names.
unit * luaW_tounit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
const unit_type * luaW_tounittype(lua_State *L, int idx)
Test if a stack element is a unit type, and return it if so.
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
std::string encode_ellipsize_mode(const PangoEllipsizeMode ellipsize_mode)
Converts a PangoEllipsizeMode to its string representation.
std::map< std::string, t_string > widget_item
PangoAlignment decode_text_alignment(const std::string &alignment)
Converts a text alignment string to a text alignment.
std::string encode_text_alignment(const PangoAlignment alignment)
Converts a PangoAlignment to its string representation.
PangoEllipsizeMode decode_ellipsize_mode(const std::string &ellipsize_mode)
Converts a text ellipsize mode string to a PangoEllipsizeMode.
void split_foreach(std::string_view s, char sep, const int flags, const F &f)
std::string::const_iterator iterator
void lua_push(lua_State *L, const T &val)
static map_location::direction n
static map_location::direction sw
static map_location::direction s