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 auto p = network::find_country_player(state, content.source);
29 auto nickname = state.world.mp_player_get_nickname(p);
30
31 std::string sender_name = sys::player_name{nickname }.to_string() + ": ";
32 std::string text_form_msg = std::string(content.body);
33 auto box = text::open_layout_box(container);
34 text::add_to_layout_box(state, container, box, sender_name, IsShadow ? text::text_color::black : text::text_color::orange);
35 text::add_to_layout_box(state, container, box, text_form_msg, color);
36 text::close_layout_box(container, box);
37 }
38};
39
40class chat_message_entry : public listbox_row_element_base<chat_message> {
41public:
42 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
43 if(name == "shield") {
44 return make_element_by_type<flag_button>(state, id);
45 } else if(name == "text_shadow") {
46 return make_element_by_type<chat_message_text<true>>(state, id);
47 } else if(name == "text") {
48 return make_element_by_type<chat_message_text<false>>(state, id);
49 } else {
50 return nullptr;
51 }
52 }
53
54 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
55 if(payload.holds_type<dcon::nation_id>()) {
56 payload.emplace<dcon::nation_id>(content.source);
58 } else if(payload.holds_type<chat_message>()) {
59 payload.emplace<chat_message>(content);
61 }
62 return listbox_row_element_base::get(state, payload);
63 }
64};
65
66template<bool ShowFull>
67class chat_message_listbox : public listbox_element_base<chat_message_entry, chat_message> {
68protected:
70 std::string_view get_row_element_name() override {
71 return "chat_entry";
72 }
73public:
74 void on_update(sys::state& state) noexcept override {
75 row_contents.clear();
76 for(uint8_t i = state.ui_state.chat_messages_index; i < uint8_t(state.ui_state.chat_messages.size()); i++) {
77 auto const& c = state.ui_state.chat_messages[i];
78 if(bool(c.source))
79 row_contents.push_back(c);
80 }
81 for(uint8_t i = 0; i < state.ui_state.chat_messages_index; i++) {
82 auto const& c = state.ui_state.chat_messages[i];
83 if(bool(c.source))
84 row_contents.push_back(c);
85 }
86 if constexpr(!ShowFull) {
87 if(!row_contents.empty()) {
88 auto to_keep = std::min(row_contents.size(), row_windows.size());
89 auto to_delete = row_contents.size() - to_keep;
90 row_contents.erase(row_contents.begin(), row_contents.begin() + to_delete);
91 }
92 }
94 if constexpr(ShowFull) {
98 }
99 }
100
101 bool is_reversed() override {
102 return false;
103 }
104
105 mouse_probe impl_probe_mouse(sys::state& state, int32_t x, int32_t y, mouse_probe_type type) noexcept override {
106 // Showing full chat? Needs a functional scrollbar!
107 if constexpr(ShowFull) {
109 } else {
110 return mouse_probe{ nullptr, ui::xy_pair{0,0} };
111 }
112 }
113};
114
116public:
117 void on_update(sys::state& state) noexcept override {
118 auto n = retrieve<dcon::nation_id>(state, parent);
119 disabled = !command::can_notify_player_kick(state, state.local_player_nation, n);
120 if(state.network_mode != sys::network_mode_type::host)
121 disabled = true;
122 }
123
124 void button_action(sys::state& state) noexcept override {
125 auto n = retrieve<dcon::nation_id>(state, parent);
126 command::notify_player_kick(state, state.local_player_nation, n);
127 }
128
131 }
132
133 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
134 auto box = text::open_layout_box(contents, 0);
135 text::localised_format_box(state, contents, box, std::string_view("tip_kick"));
136 text::close_layout_box(contents, box);
137 }
138};
139
141public:
142 void on_update(sys::state& state) noexcept override {
143 auto n = retrieve<dcon::nation_id>(state, parent);
144 disabled = !command::can_notify_player_ban(state, state.local_player_nation, n);
145 if(state.network_mode != sys::network_mode_type::host)
146 disabled = true;
147 }
148
149 void button_action(sys::state& state) noexcept override {
150 auto n = retrieve<dcon::nation_id>(state, parent);
151 command::notify_player_ban(state, state.local_player_nation, n);
152 }
153
156 }
157
158 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
159 auto box = text::open_layout_box(contents, 0);
160 text::localised_format_box(state, contents, box, std::string_view("tip_ban"));
161 text::close_layout_box(contents, box);
162 }
163};
164
166public:
167 void on_update(sys::state& state) noexcept override {
168 if(state.network_mode == sys::network_mode_type::single_player) {
170 } else {
171 auto n = retrieve<dcon::nation_id>(state, parent);
172
174 auto nickname = state.world.mp_player_get_nickname(p);
175 set_text(state, sys::player_name{nickname }.to_string());
176 }
177 }
178};
179
180class chat_player_entry : public listbox_row_element_base<dcon::nation_id> {
181public:
182 void on_create(sys::state& state) noexcept override {
184 base_data.size.y -= 6; //nudge
185 }
186
187 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
188 if(name == "player_shield") {
189 return make_element_by_type<flag_button>(state, id);
190 } else if(name == "name") {
191 return make_element_by_type<player_name_text>(state, id);
192 } else if(name == "button_kick") {
193 return make_element_by_type<player_kick_button>(state, id);
194 } else if(name == "button_ban") {
195 return make_element_by_type<player_ban_button>(state, id);
196 }
197 else {
198 return nullptr;
199 }
200 }
201};
202
203class chat_player_listbox : public listbox_element_base<chat_player_entry, dcon::nation_id> {
204protected:
205 std::string_view get_row_element_name() override {
206 return "ingame_multiplayer_entry";
207 }
208public:
209 void on_update(sys::state& state) noexcept override {
210 row_contents.clear();
211 state.world.for_each_nation([&](dcon::nation_id n) {
212 if(state.world.nation_get_is_player_controlled(n))
213 row_contents.push_back(n);
214 });
215 update(state);
216 }
217};
218
220public:
221 void on_create(sys::state& state) noexcept override {
223 base_data.size.y += 4;
225 }
226
227 void edit_box_enter(sys::state& state, std::string_view str) noexcept override {
229 if(s.empty())
230 return;
231
232 dcon::nation_id target{};
233 if(s.length() > 4 && s[0] == '@') {
234 state.world.for_each_national_identity([&](dcon::national_identity_id id) {
235 auto curr = nations::int_to_tag(state.world.national_identity_get_identifying_int(id));
236 if(curr == std::string(s).substr(1, 3))
237 target = state.world.national_identity_get_nation_from_identity_holder(id);
238 });
239 }
240
241 char body[max_chat_message_len + 1];
242 size_t len = s.length() >= max_chat_message_len ? max_chat_message_len : s.length();
243 memcpy(body, s.data(), len);
244 body[len] = '\0';
245
246 command::chat_message(state, state.local_player_nation, body, target);
247
248 Cyto::Any payload = this;
249 impl_get(state, payload);
250 }
251
252 void edit_box_tab(sys::state& state, std::string_view s) noexcept override;
253};
254
256public:
257 void on_create(sys::state& state) noexcept override {
260 }
261 void on_update(sys::state& state) noexcept override {
262 disabled = (state.network_mode == sys::network_mode_type::client) || (state.current_scene.is_lobby);
263 }
264 void button_action(sys::state& state) noexcept override {
266 command::notify_stop_game(state, state.local_player_nation);
267 }
270 }
271 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
272 if(state.current_scene.is_lobby) {
273 text::add_line(state, contents, "alice_lobby_back_tt_1");
274 }
275 if(state.network_mode == sys::network_mode_type::client) {
276 text::add_line(state, contents, "alice_lobby_back_tt_2");
277 }
278 }
279};
280
282public:
283 void on_create(sys::state& state) noexcept override {
286 }
289 }
290 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
291 text::add_line(state, contents, "reopen_with_tab");
292 }
293};
294
296private:
297 chat_message_listbox<true>* chat_message_box = nullptr;
298public:
300 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
301 if(name == "start_button") {
302 return make_element_by_type<chat_close_button>(state, id);
303 } else if(name == "background") {
304 return make_element_by_type<draggable_target>(state, id);
305 } else if(name == "chatlog") {
306 auto ptr = make_element_by_type<chat_message_listbox<true>>(state, id);
307 chat_message_box = ptr.get();
308 return ptr;
309 } else if(name == "multiplayer_list") {
310 return make_element_by_type<chat_player_listbox>(state, id);
311 } else if(name == "lobby_chat_edit") {
312 auto ptr = make_element_by_type<chat_edit_box>(state, id);
313 chat_edit = ptr.get();
314 return ptr;
315 } else if(name == "back_button") {
316 return make_element_by_type<chat_return_to_lobby_button>(state, id);
317 } else {
318 return nullptr;
319 }
320 }
321 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
322 if(payload.holds_type<chat_edit_box*>()) {
323 chat_message_box->scroll_to_bottom(state);
325 } else {
327 }
328 }
329};
330
333 state.ui_state.edit_target = static_cast<ui::chat_window*>(state.ui_state.r_chat_window)->chat_edit;
334 state.ui_state.root->move_child_to_front(state.ui_state.r_chat_window);
335}
336
339 state.ui_state.edit_target = static_cast<ui::chat_window*>(state.ui_state.chat_window)->chat_edit;
340 state.ui_state.root->move_child_to_front(state.ui_state.chat_window);
341}
342
344 state.current_scene.open_chat(state);
345}
346
347inline void chat_edit_box::edit_box_tab(sys::state& state, std::string_view s) noexcept {
348 ui::open_chat_window(state); //close/open like if tab was pressed!
349}
350
351}
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:5027
bool can_notify_player_ban(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4993
void set_map_mode(sys::state &state, mode mode)
Definition: map_modes.cpp:776
std::string int_to_tag(uint32_t v)
Definition: nations.hpp:14
dcon::mp_player_id find_country_player(sys::state &state, dcon::nation_id nation)
Definition: network.cpp:702
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:1823
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:1904
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:1923
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:1831
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
Holds important data about the game world, state, and other data regarding windowing,...
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