43 #include <boost/preprocessor/cat.hpp>
51 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
57 int n = list->get_item_count();
63 return list->get_row_grid(
i - 1);
65 int n = multi_page->get_page_count();
71 return &multi_page->page_grid(
i - 1);
76 throw std::invalid_argument(
"out of range");
80 int n = tree_view_node->count_children();
82 throw std::invalid_argument(
"out of range");
84 return &tree_view_node->get_child_at(
i - 1);
86 int n = stacked_widget->get_layer_count();
88 throw std::invalid_argument(
"out of range");
90 return stacked_widget->get_layer_grid(
i - 1);
97 return w.find(m,
false);
103 using tsetters = std::map<std::string, std::vector<std::function<bool(lua_State*,
int,
gui2::widget&,
bool)>>>;
106 template<
typename w
idget_type,
typename value_type>
109 virtual value_type
get(lua_State* L, widget_type&
w)
const = 0;
113 template<
typename w
idget_type,
typename value_type>
116 virtual void set(lua_State* L, widget_type&
w,
const value_type& value)
const = 0;
120 template<
typename w
idget_type,
typename value_type,
typename action_type,
bool setter>
124 using map_type = std::conditional_t<setter, tsetters, tgetters>;
125 using list_type =
typename map_type::mapped_type;
126 using callback_type =
typename list_type::value_type;
129 if constexpr(setter) {
131 fcn = [action = action_type()](lua_State* L,
int idx,
gui2::widget&
w,
bool nop) {
132 if(widget_type* pw =
dynamic_cast<widget_type*
>(&
w)) {
133 if(!nop) action.set(L, *pw, lua_check<value_type>(L, idx));
140 fcn = [action = action_type()](lua_State* L,
gui2::widget&
w,
bool nop) {
141 if(widget_type* pw =
dynamic_cast<widget_type*
>(&
w)) {
142 if(!nop)
lua_push(L, action.get(L, *pw));
148 list_type& list = (*map)[std::string(name_part)];
153 #define WIDGET_GETTER4(name, value_type, widgt_type, id) \
154 struct BOOST_PP_CAT(getter_, id) : public widget_getter<widgt_type, value_type> { \
155 value_type get(lua_State* L, widgt_type& w) const override; \
157 struct BOOST_PP_CAT(getter_adder_, id) { \
158 BOOST_PP_CAT(getter_adder_, id) () \
160 register_widget_attribute<widgt_type, value_type, BOOST_PP_CAT(getter_, id), false>(name); \
163 static BOOST_PP_CAT(getter_adder_, id) BOOST_PP_CAT(getter_adder_instance_, id) ; \
164 value_type BOOST_PP_CAT(getter_, id)::get([[maybe_unused]] lua_State* L, widgt_type& w) const
167 #define WIDGET_SETTER4(name, value_type, widgt_type, id) \
168 struct BOOST_PP_CAT(setter_, id) : public widget_setter<widgt_type, value_type> { \
169 void set(lua_State* L, widgt_type& w, const value_type& value) const override; \
171 struct BOOST_PP_CAT(setter_adder_, id) { \
172 BOOST_PP_CAT(setter_adder_, id) ()\
174 register_widget_attribute<widgt_type, value_type, BOOST_PP_CAT(setter_, id), true>(name); \
177 static BOOST_PP_CAT(setter_adder_, id) BOOST_PP_CAT(setter_adder_instance_, id); \
178 void BOOST_PP_CAT(setter_, id)::set([[maybe_unused]] lua_State* L, widgt_type& w, const value_type& value) const
186 #define WIDGET_GETTER(name, value_type, widgt_type) WIDGET_GETTER4(name, value_type, widgt_type, __LINE__)
188 #define WIDGET_SETTER(name, value_type, widgt_type) WIDGET_SETTER4(name, value_type, widgt_type, __LINE__)
195 return w.get_selected_row() + 1;
200 w.select_row(value - 1);
205 return w.get_selected_page() + 1;
210 w.select_page(value -1);
215 return w.current_layer() + 1;
220 w.select_layer(value - 1);
225 return w.get_value() + 1;
230 if(value >
int(
w.num_states())) {
231 throw std::invalid_argument(
"invalid index");
233 w.set_value(value - 1);
238 if(
w.num_states() == 2) {
239 return w.get_value_bool();
241 throw std::invalid_argument(
"invalid widget");
246 w.set_value_bool(value);
251 return w.get_value();
261 return w.get_value();
271 return w.get_maximum_value();
276 w.set_value_range(
w.get_minimum_value(), value);
281 return w.get_minimum_value();
286 w.set_value_range(value,
w.get_maximum_value());
291 return w.get_percentage();
296 w.set_percentage(value);
301 auto res =
w.selected_item()->describe_path();
302 for(
int&
a : res) { ++
a;}
308 auto res =
w.describe_path();
309 for(
int&
a : res) { ++
a;}
325 w.set_displayed_type(*ut);
327 w.set_displayed_unit(*u);
335 return w.get_page_count();
340 return w.get_item_count();
345 w.set_use_markup(value);
354 w.set_use_markup(
true);
365 w.set_tooltip(value);
372 ERR_LUA <<
"gui.widget.set_callback didn't exist";
375 lua_pushvalue(L, value.index);
384 visibility
flag = visibility::visible;
386 switch(lua_type(L, value.index)) {
389 ? visibility::visible
390 : visibility::invisible;
394 const std::string& str = lua_tostring(L, value.index);
395 if(str ==
"visible") {
396 flag = visibility::visible;
397 }
else if(str ==
"hidden") {
398 flag = visibility::hidden;
399 }
else if(str ==
"invisible") {
400 flag = visibility::invisible;
402 luaL_argerror(L, value.index,
"string must be one of: visible, hidden, invisible");
412 if(
flag == visibility::hidden) {
435 return sw->get_control_type();
438 return "tree_view_node";
457 ERR_LUA <<
"widget was deleted";
462 ERR_LUA <<
"cannot find window in widget callback";
472 throw std::invalid_argument(
"the widget has no window assigned");
474 lua_pushvalue(L, value.index);
484 throw std::invalid_argument(
"the widget has no window assigned");
486 lua_pushvalue(L, value.index);
498 throw std::invalid_argument(
"the widget has no window assigned");
501 throw std::invalid_argument(
"unsupported widget");
503 lua_pushvalue(L, value.index);
516 if(lua_isinteger(L, 2)) {
524 std::string_view str = lua_check<std::string_view>(L, 2);
528 for(
const auto& func : it->second) {
529 if(func(L,
w,
false)) {
534 if(
luaW_getglobal(L,
"gui",
"widget", std::string(str).c_str())) {
541 ERR_LUA <<
"invalid property of '" <<
typeid(
w).name()<<
"' widget :" << str;
542 return luaL_argerror(L, 2,
"invalid property of widget");
548 std::string_view str = lua_check<std::string_view>(L, 2);
553 for(
const auto& func : it->second) {
554 if(func(L, 3,
w,
false)) {
558 ERR_LUA <<
"none of "<< it->second.size() <<
" setters matched";
561 ERR_LUA <<
"unknown property id : " << str <<
" #known properties=" <<
setters.size();
564 ERR_LUA <<
"invalid modifiable property of '" <<
typeid(
w).name()<<
"' widget:" << str;
565 return luaL_argerror(L, 2,
"invalid modifiable property of widget");
571 std::vector<std::string> keys;
573 for(
const auto& [key, funcs] :
getters) {
574 if(key ==
"value_compat")
continue;
575 for(
const auto& func : funcs) {
576 if(func(L,
w,
true)){
583 for(
const auto& [key, funcs] :
setters) {
584 if(key ==
"value_compat")
continue;
585 if(key ==
"callback")
continue;
586 for(
const auto& func : funcs) {
587 if(func(L, 0,
w,
true)){
595 for(
auto child = iter_t(
w); !child.at_end(); child.next()) {
596 const auto& key = child->
id();
597 if(!key.empty() && key !=
w.id()) {
604 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.
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::map< std::string, t_string > widget_item
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 sw
static map_location::DIRECTION n