Project Alice
Loading...
Searching...
No Matches
gui_chat_window.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace ui {
6
7template<bool IsShadow>
9public:
10 void on_update(sys::state& state) noexcept override {
11 auto content = retrieve<chat_message>(state, parent);
12 auto border = base_data.data.text.border_size;
13 auto color = IsShadow ? text::text_color::black : (content.target ? text::text_color::orange : text::text_color::white);
14 auto container = text::create_endless_layout(state,
17 border.x,
18 border.y,
19 int16_t(base_data.size.x - border.x * 2),
20 int16_t(base_data.size.y - border.y * 2),
22 0,
24 color,
25 false });
26
27
28 std::string sender_name = std::string(state.network_state.map_of_player_names[content.source.index()].to_string_view()) + ": ";
29 std::string text_form_msg = std::string(content.body);
30 auto box = text::open_layout_box(container);
31 text::add_to_layout_box(state, container, box, sender_name, IsShadow ? text::text_color::black : text::text_color::orange);
32 text::add_to_layout_box(state, container, box, text_form_msg, color);
33 text::close_layout_box(container, box);
34 }
35};
36
37class chat_message_entry : public listbox_row_element_base<chat_message> {
38public:
39 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
40 if(name == "shield") {
41 return make_element_by_type<flag_button>(state, id);
42 } else if(name == "text_shadow") {
43 return make_element_by_type<chat_message_text<true>>(state, id);
44 } else if(name == "text") {
45 return make_element_by_type<chat_message_text<false>>(state, id);
46 } else {
47 return nullptr;
48 }
49 }
50
51 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
52 if(payload.holds_type<dcon::nation_id>()) {
53 payload.emplace<dcon::nation_id>(content.source);
55 } else if(payload.holds_type<chat_message>()) {
56 payload.emplace<chat_message>(content);
58 }
59 return listbox_row_element_base::get(state, payload);
60 }
61};
62
63template<bool ShowFull>
64class chat_message_listbox : public listbox_element_base<chat_message_entry, chat_message> {
65protected:
67 std::string_view get_row_element_name() override {
68 return "chat_entry";
69 }
70public:
71 void on_update(sys::state& state) noexcept override {
72 row_contents.clear();
73 for(uint8_t i = state.ui_state.chat_messages_index; i < uint8_t(state.ui_state.chat_messages.size()); i++) {
74 auto const& c = state.ui_state.chat_messages[i];
75 if(bool(c.source))
76 row_contents.push_back(c);
77 }
78 for(uint8_t i = 0; i < state.ui_state.chat_messages_index; i++) {
79 auto const& c = state.ui_state.chat_messages[i];
80 if(bool(c.source))
81 row_contents.push_back(c);
82 }
83 if constexpr(!ShowFull) {
84 if(!row_contents.empty()) {
85 auto to_keep = std::min(row_contents.size(), row_windows.size());
86 auto to_delete = row_contents.size() - to_keep;
87 row_contents.erase(row_contents.begin(), row_contents.begin() + to_delete);
88 }
89 }
91 if constexpr(ShowFull) {
95 }
96 }
97
98 bool is_reversed() override {
99 return false;
100 }
101
102 mouse_probe impl_probe_mouse(sys::state& state, int32_t x, int32_t y, mouse_probe_type type) noexcept override {
103 // Showing full chat? Needs a functional scrollbar!
104 if constexpr(ShowFull) {
106 } else {
107 return mouse_probe{ nullptr, ui::xy_pair{0,0} };
108 }
109 }
110};
111
113public:
114 void on_update(sys::state& state) noexcept override {
115 auto n = retrieve<dcon::nation_id>(state, parent);
116 disabled = !command::can_notify_player_kick(state, state.local_player_nation, n);
117 if(state.network_mode != sys::network_mode_type::host)
118 disabled = true;
119 }
120
121 void button_action(sys::state& state) noexcept override {
122 auto n = retrieve<dcon::nation_id>(state, parent);
123 command::notify_player_kick(state, state.local_player_nation, n);
124 }
125
128 }
129
130 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
131 auto box = text::open_layout_box(contents, 0);
132 text::localised_format_box(state, contents, box, std::string_view("tip_kick"));
133 text::close_layout_box(contents, box);
134 }
135};
136
138public:
139 void on_update(sys::state& state) noexcept override {
140 auto n = retrieve<dcon::nation_id>(state, parent);
141 disabled = !command::can_notify_player_ban(state, state.local_player_nation, n);
142 if(state.network_mode != sys::network_mode_type::host)
143 disabled = true;
144 }
145
146 void button_action(sys::state& state) noexcept override {
147 auto n = retrieve<dcon::nation_id>(state, parent);
148 command::notify_player_ban(state, state.local_player_nation, n);
149 }
150
153 }
154
155 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
156 auto box = text::open_layout_box(contents, 0);
157 text::localised_format_box(state, contents, box, std::string_view("tip_ban"));
158 text::close_layout_box(contents, box);
159 }
160};
161
163public:
164 void on_update(sys::state& state) noexcept override {
165 if(state.network_mode == sys::network_mode_type::single_player) {
167 } else {
168 auto n = retrieve<dcon::nation_id>(state, parent);
169 set_text(state, std::string(state.network_state.map_of_player_names[n.index()].to_string_view()));
170 }
171 }
172};
173
174class chat_player_entry : public listbox_row_element_base<dcon::nation_id> {
175public:
176 void on_create(sys::state& state) noexcept override {
178 base_data.size.y -= 6; //nudge
179 }
180
181 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
182 if(name == "player_shield") {
183 return make_element_by_type<flag_button>(state, id);
184 } else if(name == "name") {
185 return make_element_by_type<player_name_text>(state, id);
186 } else if(name == "button_kick") {
187 return make_element_by_type<player_kick_button>(state, id);
188 } else {
189 return nullptr;
190 }
191 }
192};
193
194class chat_player_listbox : public listbox_element_base<chat_player_entry, dcon::nation_id> {
195protected:
196 std::string_view get_row_element_name() override {
197 return "ingame_multiplayer_entry";
198 }
199public:
200 void on_update(sys::state& state) noexcept override {
201 row_contents.clear();
202 state.world.for_each_nation([&](dcon::nation_id n) {
203 if(state.world.nation_get_is_player_controlled(n))
204 row_contents.push_back(n);
205 });
206 update(state);
207 }
208};
209
211public:
212 void on_create(sys::state& state) noexcept override {
214 base_data.size.y += 4;
216 }
217
218 void edit_box_enter(sys::state& state, std::string_view str) noexcept override {
220 if(s.empty())
221 return;
222
223 dcon::nation_id target{};
224 if(s.length() > 4 && s[0] == '@') {
225 state.world.for_each_national_identity([&](dcon::national_identity_id id) {
226 auto curr = nations::int_to_tag(state.world.national_identity_get_identifying_int(id));
227 if(curr == std::string(s).substr(1, 3))
228 target = state.world.national_identity_get_nation_from_identity_holder(id);
229 });
230 }
231
232 char body[max_chat_message_len + 1];
233 size_t len = s.length() >= max_chat_message_len ? max_chat_message_len : s.length();
234 memcpy(body, s.data(), len);
235 body[len] = '\0';
236
237 command::chat_message(state, state.local_player_nation, body, target);
238
239 Cyto::Any payload = this;
240 impl_get(state, payload);
241 }
242
243 void edit_box_tab(sys::state& state, std::string_view s) noexcept override;
244};
245
247public:
248 void on_create(sys::state& state) noexcept override {
251 }
252 void on_update(sys::state& state) noexcept override {
253 disabled = (state.network_mode == sys::network_mode_type::client) || (state.current_scene.is_lobby);
254 }
255 void button_action(sys::state& state) noexcept override {
257 command::notify_stop_game(state, state.local_player_nation);
258 }
261 }
262 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
263 if(state.current_scene.is_lobby) {
264 text::add_line(state, contents, "alice_lobby_back_tt_1");
265 }
266 if(state.network_mode == sys::network_mode_type::client) {
267 text::add_line(state, contents, "alice_lobby_back_tt_2");
268 }
269 }
270};
271
273public:
274 void on_create(sys::state& state) noexcept override {
277 }
280 }
281 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
282 text::add_line(state, contents, "reopen_with_tab");
283 }
284};
285
287private:
288 chat_message_listbox<true>* chat_message_box = nullptr;
289public:
291 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
292 if(name == "start_button") {
293 return make_element_by_type<chat_close_button>(state, id);
294 } else if(name == "background") {
295 return make_element_by_type<draggable_target>(state, id);
296 } else if(name == "chatlog") {
297 auto ptr = make_element_by_type<chat_message_listbox<true>>(state, id);
298 chat_message_box = ptr.get();
299 return ptr;
300 } else if(name == "multiplayer_list") {
301 return make_element_by_type<chat_player_listbox>(state, id);
302 } else if(name == "lobby_chat_edit") {
303 auto ptr = make_element_by_type<chat_edit_box>(state, id);
304 chat_edit = ptr.get();
305 return ptr;
306 } else if(name == "back_button") {
307 return make_element_by_type<chat_return_to_lobby_button>(state, id);
308 } else {
309 return nullptr;
310 }
311 }
312 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
313 if(payload.holds_type<chat_edit_box*>()) {
314 chat_message_box->scroll_to_bottom(state);
316 } else {
318 }
319 }
320};
321
324 state.ui_state.edit_target = static_cast<ui::chat_window*>(state.ui_state.r_chat_window)->chat_edit;
325 state.ui_state.root->move_child_to_front(state.ui_state.r_chat_window);
326}
327
330 state.ui_state.edit_target = static_cast<ui::chat_window*>(state.ui_state.chat_window)->chat_edit;
331 state.ui_state.root->move_child_to_front(state.ui_state.chat_window);
332}
333
335 state.current_scene.open_chat(state);
336}
337
338inline void chat_edit_box::edit_box_tab(sys::state& state, std::string_view s) noexcept {
339 ui::open_chat_window(state); //close/open like if tab was pressed!
340}
341
342}
void set_button_text(sys::state &state, std::string const &new_text)
void on_create(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
void edit_box_enter(sys::state &state, std::string_view str) noexcept override
void edit_box_tab(sys::state &state, std::string_view s) noexcept override
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
std::string_view get_row_element_name() override
void on_update(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
std::string_view get_row_element_name() override
void on_update(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void button_action(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
chat_edit_box * chat_edit
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
void on_create(sys::state &state) noexcept override
element_base * parent
virtual message_result get(sys::state &state, Cyto::Any &payload) noexcept
bool is_visible() const
message_result impl_get(sys::state &state, Cyto::Any &payload) noexcept
virtual void on_create(sys::state &state) noexcept
element_data base_data
void set_visible(sys::state &state, bool vis)
virtual mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
void on_update(sys::state &state) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void button_action(sys::state &state) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void button_action(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
void on_update(sys::state &state) noexcept override
void set_text(sys::state &state, std::string const &new_text)
bool can_notify_player_kick(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4599
bool can_notify_player_ban(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4568
void set_map_mode(sys::state &state, mode mode)
Definition: map_modes.cpp:796
std::string int_to_tag(uint32_t v)
Definition: nations.hpp:10
std::string_view remove_surrounding_whitespace(std::string_view txt)
Definition: parsers.cpp:381
void add_to_layout_box(sys::state &state, layout_base &dest, layout_box &box, embedded_flag ico)
Definition: text.cpp:1165
layout_box open_layout_box(layout_base &dest, int32_t indent)
Definition: text.cpp:1799
void localised_format_box(sys::state &state, layout_base &dest, layout_box &box, std::string_view key, text::substitution_map const &sub)
Definition: text.cpp:1880
endless_layout create_endless_layout(sys::state &state, layout &dest, layout_parameters const &params)
Definition: text.cpp:1100
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
Definition: text.cpp:1899
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
Definition: text.cpp:617
void close_layout_box(columnar_layout &dest, layout_box &box)
Definition: text.cpp:1807
constexpr uint32_t max_chat_message_len
Definition: constants.hpp:586
void open_chat_during_game(sys::state &state)
void open_chat_before_game(sys::state &state)
tooltip_behavior
message_result
void open_chat_window(sys::state &state)
uchar uint8_t
dcon::nation_id source
union ui::element_data::internal_data data
element_base * chat_window
uint8_t chat_messages_index
std::array< chat_message, 32 > chat_messages
element_base * r_chat_window
std::unique_ptr< element_base > root
element_base * edit_target
xy_pair border_size