5#include <unordered_map>
12#include "dcon_generated.hpp"
37 for(
auto& c : children) {
40 auto res = c->impl_probe_mouse(
state, x - relative_location.x, y - relative_location.y,
type);
50 for(
auto& c : children) {
61 for(
auto& c : children) {
63 c->impl_on_update(
state);
68 for(
auto& c : children) {
69 c->impl_on_reset_text(
state);
75 for(
auto& c : children) {
84 for(
size_t i = children.size(); i-- > 0;) {
85 if(children[i]->is_visible()) {
87 children[i]->impl_render(
state, x + relative_location.x, y + relative_location.y);
93 if(
auto it = std::find_if(children.begin(), children.end(), [child](std::unique_ptr<element_base>& p) { return p.get() == child; }); it != children.end()) {
94 if(it + 1 != children.end())
95 std::rotate(it, it + 1, children.end());
96 auto temp = std::move(children.back());
98 temp->parent =
nullptr;
101 return std::unique_ptr<element_base>{};
104 if(
auto it = std::find_if(children.begin(), children.end(), [child](std::unique_ptr<element_base>& p) { return p.get() == child; }); it != children.end()) {
105 if(it != children.begin())
106 std::rotate(children.begin(), it, it + 1);
110 if(
auto it = std::find_if(children.begin(), children.end(), [child](std::unique_ptr<element_base>& p) { return p.get() == child; }); it != children.end()) {
111 if(it + 1 != children.end())
112 std::rotate(it, it + 1, children.end());
116 child->parent =
this;
117 children.emplace_back(std::move(child));
118 if(children.size() > 1) {
119 std::rotate(children.begin(), children.end() - 1, children.end());
123 child->parent =
this;
124 children.emplace_back(std::move(child));
127 if(
auto it = std::find_if(children.begin(), children.end(), [&
state,
name](std::unique_ptr<element_base>& p) { return parsers::lowercase_str(state.to_string_view(p->base_data.name)) == parsers::lowercase_str(name); }); it != children.end()) {
133 if(0 <= index && index < int32_t(children.size()))
134 return children[index].
get();
139 if(!is_under_mouse || !is_interactable) {
157 frame = base_data.data.image.frame();
162 dcon::gfx_object_id gid;
164 gid = base_data.data.image.gfx_object;
166 gid = base_data.data.button.button_image;
170 auto& gfx_def =
state.ui_defs.gfx[gid];
171 if(gfx_def.primary_texture_handle) {
174 gfx_def.type_dependent,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
176 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
177 get_horizontal_flip(
state));
178 }
else if(gfx_def.number_of_frames > 1) {
180 gfx_def.number_of_frames,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
182 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
183 get_horizontal_flip(
state));
186 float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
188 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
189 get_horizontal_flip(
state));
196 dcon::gfx_object_id gid;
198 gid = base_data.data.image.gfx_object;
200 gid = base_data.data.button.button_image;
203 auto const& gfx_def =
state.ui_defs.gfx[gid];
204 if(gfx_def.primary_texture_handle) {
205 if(gfx_def.number_of_frames > 1) {
207 gfx_def.number_of_frames,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
210 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
211 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
216 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
217 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
225 dcon::gfx_object_id gid = base_data.data.image.gfx_object;
227 auto const& gfx_def =
state.ui_defs.gfx[gid];
228 auto secondary_texture_handle = dcon::texture_id(gfx_def.type_dependent - 1);
229 if(gfx_def.primary_texture_handle) {
231 progress,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
234 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
235 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
243 float amount = (r + g + b) / 4.f;
244 return sys::pack_color(std::min(1.f, amount + 0.1f), std::min(1.f, amount + 0.1f), std::min(1.f, amount + 0.1f));
247 return sys::pack_color(std::min(1.f, r + 0.1f), std::min(1.f, g + 0.1f), std::min(1.f, b + 0.1f));
250 float amount = (r + g + b) / 4.f;
265 auto& current_font =
state.font_collection.get_font(
state, font_index);
267 if(std::holds_alternative<text::embedded_flag>(t.
source)) {
270 std::get<text::embedded_flag>(t.
source),
277 }
else if(std::holds_alternative<text::embedded_unit_icon>(t.
source)) {
280 std::get<text::embedded_unit_icon>(t.
source),
287 }
else if(std::holds_alternative<text::embedded_icon>(t.
source)) {
290 std::get<text::embedded_icon>(t.
source),
314 dcon::gfx_object_id gid;
316 gid = base_data.data.image.gfx_object;
318 gid = base_data.data.button.button_image;
321 auto const& gfx_def =
state.ui_defs.gfx[gid];
322 if(gfx_def.primary_texture_handle) {
341 if(gfx_def.number_of_frames > 1) {
343 gfx_def.number_of_frames,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
346 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
347 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
352 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
353 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
361 if(internal_layout.contents.empty())
364 auto linesz =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
367 auto ycentered = (base_data.size.y - linesz) / 2;
370 for(
auto& t : internal_layout.contents) {
375 float(y + int32_t(ycentered)),
376 base_data.data.button.font_handle,
384 dcon::gfx_object_id gid;
386 gid = base_data.data.image.gfx_object;
388 gid = base_data.data.button.button_image;
391 auto const& gfx_def =
state.ui_defs.gfx[gid];
392 if(gfx_def.primary_texture_handle) {
406 if(gfx_def.number_of_frames > 1) {
408 gfx_def.number_of_frames,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
411 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
412 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
417 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
418 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
423 if(internal_layout.contents.empty())
426 auto linesz =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
429 auto ycentered = (base_data.size.y - linesz) / 2;
432 for(
auto& t : internal_layout.contents) {
437 float(y + int32_t(ycentered)),
438 base_data.data.button.font_handle,
513 return ogl::color3f{232.0f / 255.0f, 210.0f / 255.0f, 124.0f / 255.0f};
515 return ogl::color3f{ 150.0f / 255.0f, 75.0f / 255.0f, 0.f };
538 auto base_text_handle = base_data.data.button.txt;
540 if(base_text_handle) {
542 internal_layout.contents.clear();
543 internal_layout.number_of_lines = 0;
548 sl.add_text(
state, cached_text);
554 on_reset_text(
state);
566 if(ch >= 32 && ch != U
'`' && ch != 127) {
567 auto s = std::string(get_text(
state));
568 s += char(ch & 0xff);
571 edit_box_update(
state, s);
572 }
else if(ch == 0x16) {
574 std::wstring return_value;
575 if(OpenClipboard(
state.win_ptr->hwnd)) {
576 HGLOBAL hClipboardData = GetClipboardData(CF_UNICODETEXT);
578 if(hClipboardData != NULL) {
579 size_t byteSize = GlobalSize(hClipboardData);
580 void* memory = GlobalLock(hClipboardData);
582 const wchar_t*
text =
reinterpret_cast<const wchar_t*
>(memory);
583 return_value = std::wstring(
text,
text + byteSize /
sizeof(
wchar_t));
584 GlobalUnlock(hClipboardData);
585 if(return_value.length() > 0 && return_value.back() == 0) {
586 return_value.pop_back();
592 if(return_value.size() > 0) {
594 auto new_text = std::string(get_text(
state)) + utf8_val;
595 edit_index += int32_t(utf8_val.length());
596 set_text(
state, new_text);
597 edit_box_update(
state, new_text);
607 auto s = std::string(get_text(
state));
610 edit_box_enter(
state, s);
619 edit_box_tab(
state, s);
625 edit_box_down(
state);
628 edit_box_backtick(
state);
631 edit_box_back_slash(
state);
634 edit_index = std::max<int32_t>(edit_index - 1, 0);
637 edit_index = std::min<int32_t>(edit_index + 1, int32_t(s.length()));
640 if(edit_index < int32_t(s.length())) {
641 s.erase(edit_index, 1);
643 edit_box_update(
state, s);
648 int32_t index = edit_index - 1;
650 while(index > 0 && (s.at(index) !=
' ' || !skip)) {
651 if(s.at(index) !=
' ')
655 s.erase(index, edit_index);
658 edit_box_update(
state, s);
659 }
else if(edit_index > 0 && edit_index <= int32_t(s.length())) {
660 s.erase(edit_index - 1, 1);
663 edit_box_update(
state, s);
688 on_reset_text(
state);
693 dcon::texture_id background_texture_id;
704 if(
bool(background_texture_id)) {
707 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
712 auto old_s = std::string(get_text(
state));
713 auto blink_s = std::string(get_text(
state));
714 blink_s.insert(
size_t(edit_index), 1,
'|');
715 set_text(
state, blink_s);
717 set_text(
state, old_s);
724 for(
auto& t : internal_layout.contents) {
742 float min = *std::min_element(datapoints.begin(), datapoints.end());
743 float max = *std::max_element(datapoints.begin(), datapoints.end());
744 float y_height = max - min;
745 std::vector<float> scaled_datapoints = std::vector<float>(
count);
746 if(y_height == 0.f) {
747 for(
size_t i = 0; i <
count; i++) {
748 scaled_datapoints[i] = .5f;
751 for(
size_t i = 0; i <
count; i++) {
752 scaled_datapoints[i] = (datapoints[i] - min) / y_height;
757 lines.set_y(scaled_datapoints.data());
762 float y_height = max - min;
763 std::vector<float> scaled_datapoints = std::vector<float>(
count);
764 if(y_height == 0.f) {
765 for(
size_t i = 0; i <
count; i++) {
766 scaled_datapoints[i] = .5f;
769 for(
size_t i = 0; i <
count; i++) {
770 scaled_datapoints[i] = (datapoints[i] - min) / y_height;
775 lines.set_y(scaled_datapoints.data());
826 uint16_t font_handle = 0;
851 internal_layout.contents.clear();
852 internal_layout.number_of_lines = 0;
858 sl.add_text(
state, cached_text);
865 internal_layout.contents.clear();
866 internal_layout.number_of_lines = 0;
872 sl.add_text(
state, cached_text);
878 on_reset_text(
state);
884 auto linesz =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
887 auto ycentered = (base_data.size.y - linesz) / 2;
889 for(
auto& t : internal_layout.contents) {
894 float(y + int32_t(ycentered)),
895 base_data.data.button.font_handle,
901 for(
auto& t : internal_layout.contents) {
905 float(x + base_data.data.text.border_size.x) + t.x,
906 float(y + base_data.data.text.border_size.y),
907 base_data.data.button.font_handle,
935 auto old_handle = base_data.data.text_common.font_handle;
936 base_data.data.text_common.font_handle &= ~(0x01 << 7);
937 auto old_value = base_data.data.text_common.font_handle & 0x3F;
938 base_data.data.text_common.font_handle &= ~(0x003F);
939 base_data.data.text_common.font_handle |= (old_value - 2);
942 base_data.data.text_common.font_handle = old_handle;
945 auto old_handle = base_data.data.text_common.font_handle;
946 base_data.data.text_common.font_handle &= ~(0x01 << 7);
947 auto old_value = base_data.data.text_common.font_handle & 0x3F;
948 base_data.data.text_common.font_handle &= ~(0x003F);
949 base_data.data.text_common.font_handle |= (old_value - 2);
952 base_data.data.text_common.font_handle = old_handle;
959 auto linesz =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
962 auto ycentered = (base_data.size.y - linesz) / 2;
964 for(
auto& t : internal_layout.contents) {
969 float(y + int32_t(ycentered)),
970 base_data.data.button.font_handle,
976 for(
auto& t : internal_layout.contents) {
980 float(x + base_data.data.text.border_size.x) + t.x,
981 float(y + base_data.data.text.border_size.y),
982 base_data.data.button.font_handle,
993 line_height =
state.font_collection.line_height(
state, base_data.data.text.font_handle);
994 visible_lines = base_data.size.y / std::max<int32_t>(int32_t(line_height), 1);
1004 for(
auto& t : internal_layout.contents) {
1005 float line_offset = t.y - line_height * float(current_line);
1007 if(0 <= line_offset && line_offset < base_data.size.y) {
1012 float(y + line_offset),
1013 base_data.data.text.font_handle,
1023 auto const* chunk = internal_layout.get_chunk_from_position(x, y + int32_t(line_height *
float(current_line)));
1024 if(chunk !=
nullptr) {
1025 if(std::holds_alternative<dcon::nation_id>(chunk->source)) {
1027 state.open_diplomacy(std::get<dcon::nation_id>(chunk->source));
1028 auto cap =
state.world.nation_get_capital(std::get<dcon::nation_id>(chunk->source));
1030 auto map_pos =
state.world.province_get_mid_point(cap);
1031 map_pos.x /= float(
state.map_state.map_data.size_x);
1032 map_pos.y /= float(
state.map_state.map_data.size_y);
1033 map_pos.y = 1.0f - map_pos.y;
1034 state.map_state.set_pos(map_pos);
1036 }
else if(std::holds_alternative<dcon::province_id>(chunk->source)) {
1037 auto prov = std::get<dcon::province_id>(chunk->source);
1038 if(prov && prov.value <
state.province_definitions.first_sea_province.value) {
1040 state.map_state.set_selected_province(prov);
1044 state.map_state.center_map_on_province(
state, prov);
1046 }
else if(std::holds_alternative<dcon::state_instance_id>(chunk->source)) {
1047 auto s = std::get<dcon::state_instance_id>(chunk->source);
1048 auto prov =
state.world.state_instance_get_capital(s);
1049 if(prov && prov.id.value <
state.province_definitions.first_sea_province.value) {
1051 state.map_state.set_selected_province(prov);
1055 state.map_state.center_map_on_province(
state, prov);
1057 }
else if(std::holds_alternative<dcon::national_identity_id>(chunk->source)) {
1058 auto id = std::get<dcon::national_identity_id>(chunk->source);
1059 auto nat =
state.world.national_identity_get_nation_from_identity_holder(
id);
1063 auto cap =
state.world.nation_get_capital(nat);
1065 auto map_pos =
state.world.province_get_mid_point(cap);
1066 map_pos.x /= float(
state.map_state.map_data.size_x);
1067 map_pos.y /= float(
state.map_state.map_data.size_y);
1068 map_pos.y = 1.0f - map_pos.y;
1069 state.map_state.set_pos(map_pos);
1072 }
else if(std::holds_alternative<dcon::state_definition_id>(chunk->source)) {
1073 auto s = std::get<dcon::state_definition_id>(chunk->source);
1074 auto prov_rng =
state.world.state_definition_get_abstract_state_membership(s);
1075 dcon::province_id
prov = prov_rng.begin() != prov_rng.end() ? (*prov_rng.begin()).get_province().id : dcon::province_id{ };
1076 if(prov &&
prov.value <
state.province_definitions.first_sea_province.value) {
1078 state.map_state.set_selected_province(prov);
1082 state.map_state.center_map_on_province(state, prov);
1095 if(line_height == 0.f)
1100 auto chunk = internal_layout.get_chunk_from_position(x, y + int32_t(line_height *
float(current_line)));
1103 if(std::holds_alternative<dcon::nation_id>(chunk->source)
1104 || std::holds_alternative<dcon::province_id>(chunk->source)
1105 || std::holds_alternative<dcon::state_instance_id>(chunk->source)
1106 || std::holds_alternative<dcon::national_identity_id>(chunk->source)
1107 || std::holds_alternative<dcon::state_definition_id>(chunk->source)) {
1127 line_height =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
1128 if(line_height == 0.f)
1130 visible_lines = base_data.size.y / int32_t(line_height);
1135 on_reset_text(
state);
1140 if(internal_layout.contents.empty())
1144 if(line_height == 0.f)
1146 for(
auto& t : internal_layout.contents) {
1147 float line_offset = t.y - line_height * float(current_line);
1148 if(0 <= line_offset && line_offset < base_data.size.y) {
1153 float(y + line_offset),
1154 base_data.data.button.font_handle,
1165 dcon::gfx_object_id gfx_handle;
1174 auto const& gfx_def =
state.ui_defs.gfx[gfx_handle];
1175 if(gfx_def.size.x != 0) {
1176 dat.
size = gfx_def.size;
1178 auto tex_handle = gfx_def.primary_texture_handle;
1181 dat.
size.
y = int16_t(
state.open_gl.asset_textures[tex_handle].size_y);
1182 dat.
size.
x = int16_t(
state.open_gl.asset_textures[tex_handle].size_x / gfx_def.number_of_frames);
1196 if(it->second.generator) {
1197 auto res = it->second.generator(
state, it->second.definition);
1199 std::memcpy(&(res->base_data), &(
state.ui_defs.gui[it->second.definition]),
sizeof(
ui::element_data));
1201 res->on_create(
state);
1207 return std::unique_ptr<element_base>{};
1211 units_root = std::make_unique<container_base>();
1212 rgos_root = std::make_unique<container_base>();
1214 root = std::make_unique<container_base>();
1217 tooltip = std::make_unique<tool_tip>();
1225 auto first_child = base_data.data.window.first_child;
1226 auto num_children = base_data.data.window.num_children;
1227 for(
auto ex :
state.ui_defs.extensions) {
1228 if(ex.window == base_data.name) {
1234 this->add_child_to_back(std::move(ch_res));
1238 for(
uint32_t i = num_children; i-- > 0;) {
1239 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(i + first_child.index()));
1245 this->add_child_to_back(std::move(ch_res));
1254 if(location_abs.x <= oldx && oldx < base_data.size.x + location_abs.x && location_abs.y <= oldy &&
1255 oldy < base_data.size.y + location_abs.y) {
1256 xy_pair new_abs_pos = location_abs;
1257 new_abs_pos.
x += int16_t(x - oldx);
1258 new_abs_pos.
y += int16_t(y - oldy);
1261 new_abs_pos.
x = int16_t(std::clamp(int32_t(new_abs_pos.
x), 0,
ui_width(
state) - base_data.size.x));
1263 new_abs_pos.
y = int16_t(std::clamp(int32_t(new_abs_pos.
y), 0,
ui_height(
state) - base_data.size.y));
1265 if(
state.world.locale_get_native_rtl(
state.font_collection.get_current_locale())) {
1266 base_data.position.x -= int16_t(new_abs_pos.
x - location_abs.x);
1268 base_data.position.x += int16_t(new_abs_pos.
x - location_abs.x);
1270 base_data.position.y += int16_t(new_abs_pos.
y - location_abs.y);
1276 if(distribution.size() > 0)
1282 base_data.position.x -= base_data.size.x;
1283 radius = float(base_data.size.x);
1284 base_data.size.x *= 2;
1285 base_data.size.y *= 2;
1290 std::sort(distribution.begin(), distribution.end(), [](
auto const& a,
auto const& b) { return a.value > b.value; });
1292 for(
auto& e : distribution) {
1295 int32_t int_total = 0;
1298 for(
auto& e : distribution) {
1299 auto ivalue = int32_t(e.value *
float(resolution) / total);
1302 int_total += ivalue;
1305 distribution.clear();
1308 if(int_total < resolution && distribution.size() > 0) {
1309 auto rem = resolution - int_total;
1311 for(
auto& e : distribution) {
1318 }
else if(int_total > resolution) {
1323 for(
auto& e : distribution) {
1325 auto slice_count = size_t(e.slices);
1327 for(
size_t j = 0; j < slice_count; j++) {
1328 data_texture.data[(i + j) * channels] =
uint8_t(color & 0xFF);
1329 data_texture.data[(i + j) * channels + 1] =
uint8_t(color >> 8 & 0xFF);
1330 data_texture.data[(i + j) * channels + 2] =
uint8_t(color >> 16 & 0xFF);
1335 for(; i < resolution; i++) {
1336 data_texture.data[i * channels] =
uint8_t(0);
1337 data_texture.data[i * channels + 1] =
uint8_t(0);
1338 data_texture.data[i * channels + 2] =
uint8_t(0);
1341 data_texture.data_updated =
true;
1346 float const PI = 3.141592653589793238463f;
1347 float dx = float(x) - radius;
1348 float dy = float(y) - radius;
1350 if(dx != 0.0f || dy != 0.0f) {
1351 float dist = std::sqrt(dx * dx + dy * dy);
1352 float angle = std::acos(-dx / dist);
1354 angle = PI + (PI - angle);
1356 index = size_t(angle / (2.f * PI) *
float(resolution));
1358 for(
auto const& e : distribution) {
1359 if(index <
size_t(e.slices)) {
1360 populate_tooltip(
state, e.key, e.value, contents);
1363 index -= size_t(e.slices);
1371 if constexpr(!std::is_same_v<dcon::nation_id, T>)
1381template<
class SrcT,
class DemoT>
1383 this->distribution.clear();
1388 this->parent->impl_get(
state, obj_id_payload);
1389 float total_pops = 0.f;
1391 for_each_demo(
state, [&](DemoT demo_id) {
1393 if(obj_id_payload.
holds_type<dcon::province_id>()) {
1394 auto demo_key = demographics::to_key(state, demo_id);
1395 auto prov_id = any_cast<dcon::province_id>(obj_id_payload);
1396 volume = state.world.province_get_demographics(prov_id, demo_key);
1397 }
else if(obj_id_payload.
holds_type<dcon::nation_id>()) {
1398 auto demo_key = demographics::to_key(state, demo_id);
1399 auto nat_id = any_cast<dcon::nation_id>(obj_id_payload);
1400 volume = state.world.nation_get_demographics(nat_id, demo_key);
1403 if constexpr(std::is_same_v<SrcT, dcon::pop_id>) {
1404 if(obj_id_payload.holds_type<dcon::pop_id>()) {
1405 auto demo_key = pop_demographics::to_key(state, demo_id);
1406 auto pop_id = any_cast<dcon::pop_id>(obj_id_payload);
1407 volume = pop_demographics::get_demo(state, pop_id, demo_key);
1411 this->distribution.emplace_back(demo_id, volume);
1415 this->update_chart(
state);
1419 base_data.data.scrollbar.flags &=
~ui::scrollbar_data::step_size_mask;
1420 scrollbar::on_create(
state);
1423void autoscaling_scrollbar::scale_to_parent() {
1424 base_data.size.y = parent->base_data.size.y;
1425 base_data.data.scrollbar.border_size = base_data.size;
1426 base_data.position.x = parent->base_data.size.x;
1428 left->base_data.position.y = parent->base_data.size.y -
left->base_data.size.y;
1429 right->base_data.position.y = 0;
1430 track->base_data.size.y = parent->base_data.size.y - 2 *
right->base_data.size.y;
1431 track->base_data.position.y =
right->base_data.size.y;
1432 track->base_data.position.x = 5;
1433 slider->base_data.position.x = 0;
1434 settings.track_size = track->base_data.size.y;
1436 left->step_size = -settings.scaling_factor;
1437 right->step_size = -settings.scaling_factor;
1442 impl_get(
state, payload);
1446 auto res = std::make_unique<multiline_text_element_base>();
1449 res->base_data.position.x = 0;
1450 res->base_data.position.y = 0;
1451 res->on_create(
state);
1452 delegate = res.get();
1454 add_child_to_front(std::move(res));
1456 auto ptr = make_element_by_type<multiline_text_scrollbar>(
state,
"standardlistbox_slider");
1458 add_child_to_front(std::move(ptr));
1459 text_scrollbar->scale_to_parent();
1463 if(delegate->internal_layout.number_of_lines > delegate->visible_lines) {
1464 text_scrollbar->set_visible(
state,
true);
1465 text_scrollbar->change_settings(
state,
1468 text_scrollbar->set_visible(
state,
false);
1469 delegate->current_line = 0;
1474 if(delegate->internal_layout.number_of_lines > delegate->visible_lines) {
1475 text_scrollbar->update_scaled_value(
state, text_scrollbar->scaled_value() + std::clamp(-amount, -1.f, 1.f));
1476 delegate->current_line = int32_t(text_scrollbar->scaled_value());
1477 return message_result::consumed;
1479 return message_result::unseen;
1484 auto event = any_cast<multiline_text_scroll_event>(payload);
1485 delegate->current_line =
event.new_value;
1486 return message_result::consumed;
1488 return message_result::unseen;
1492template<
class RowWinT,
class RowConT>
1503 return message_result::unseen;
1507template<
class RowConT>
1509 if(payload.holds_type<RowConT>()) {
1510 payload.emplace<RowConT>(content);
1511 return message_result::consumed;
1513 content = any_cast<wrapped_listbox_row_content<RowConT>>(payload).content;
1514 impl_on_update(
state);
1515 return message_result::consumed;
1517 return message_result::unseen;
1520template<
class RowConT>
1522 if(payload.holds_type<RowConT>()) {
1523 payload.emplace<RowConT>(content);
1524 return message_result::consumed;
1526 content = any_cast<wrapped_listbox_row_content<RowConT>>(payload).content;
1528 return message_result::consumed;
1530 return message_result::unseen;
1533template<
class RowWinT,
class RowConT>
1535 auto content_off_screen = int32_t(row_contents.size() - row_windows.size());
1536 int32_t scroll_pos = list_scrollbar->raw_value();
1537 if(content_off_screen <= 0) {
1538 list_scrollbar->set_visible(
state,
false);
1542 list_scrollbar->set_visible(
state,
true);
1543 scroll_pos = std::min(scroll_pos, content_off_screen);
1547 auto i = int32_t(row_contents.size()) - scroll_pos - 1;
1548 for(int32_t rw_i = int32_t(row_windows.size()) - 1; rw_i >= 0; rw_i--) {
1549 RowWinT* row_window = row_windows[size_t(rw_i)];
1551 row_window->set_visible(
state,
true);
1552 auto prior_content = retrieve<RowConT>(
state, row_window);
1553 auto new_content = row_contents[i--];
1555 if(prior_content != new_content) {
1557 if(!row_window->is_visible()) {
1558 row_window->set_visible(
state,
true);
1560 row_window->impl_on_update(
state);
1563 row_window->set_visible(
state,
true);
1566 row_window->set_visible(
state,
false);
1570 auto i = size_t(scroll_pos);
1571 for(RowWinT* row_window : row_windows) {
1572 if(i < row_contents.size()) {
1573 auto prior_content = retrieve<RowConT>(
state, row_window);
1574 auto new_content = row_contents[i++];
1576 if(prior_content != new_content) {
1578 if(!row_window->is_visible()) {
1579 row_window->set_visible(
state,
true);
1581 row_window->impl_on_update(
state);
1584 row_window->set_visible(
state,
true);
1587 row_window->set_visible(
state,
false);
1593template<
class RowWinT,
class RowConT>
1595 if(row_contents.size() > row_windows.size()) {
1596 amount = is_reversed() ? -amount : amount;
1597 list_scrollbar->update_raw_value(
state, list_scrollbar->raw_value() + (amount < 0 ? 1 : -1));
1600 return message_result::consumed;
1602 return message_result::unseen;
1605template<
class RowWinT,
class RowConT>
1608 for(
auto rc : row_contents) {
1611 list_scrollbar->update_raw_value(
state, list_size);
1616template<
typename contents_type>
1618 if(int32_t(row_contents.size()) > visible_row_count) {
1620 list_scrollbar->update_raw_value(
state, list_scrollbar->raw_value() + (amount < 0 ? 1 : -1));
1621 impl_on_update(
state);
1622 return message_result::consumed;
1624 return message_result::unseen;
1627template<
typename contents_type>
1629 auto content_off_screen = int32_t(row_contents.size()) - visible_row_count;
1630 int32_t scroll_pos = list_scrollbar->raw_value();
1632 if(content_off_screen <= 0) {
1634 list_scrollbar->update_raw_value(
state, 0);
1637 for(; i < int32_t(row_contents.size()); ++i) {
1638 row_windows[i]->set_visible(
state,
true);
1640 for(; i < int32_t(row_windows.size()); ++i) {
1641 row_windows[i]->set_visible(
state,
false);
1645 list_scrollbar->set_visible(
state,
true);
1646 scroll_pos = std::min(scroll_pos, content_off_screen);
1649 for(; i < visible_row_count; ++i) {
1650 row_windows[i]->set_visible(
state,
true);
1652 for(; i < int32_t(row_windows.size()); ++i) {
1653 row_windows[i]->set_visible(
state,
false);
1658template<
typename contents_type>
1661 impl_on_update(
state);
1662 return message_result::consumed;
1665 for(int32_t index = 0; index < int32_t(row_windows.size()); ++index) {
1666 if(row_windows[index] == ptr.
row) {
1667 stored_index = index + list_scrollbar->raw_value();
1668 return message_result::consumed;
1672 return message_result::consumed;
1673 }
else if(payload.holds_type<contents_type>()) {
1674 if(0 <= stored_index && stored_index < int32_t(row_contents.size())) {
1675 payload = row_contents[stored_index];
1677 return message_result::consumed;
1679 return message_result::unseen;
1683template<
typename contents_type>
1685 int32_t row_height = row_windows[0]->
base_data.
position.
y + row_windows[0]->base_data.size.y;
1686 int32_t height_covered = int32_t(row_windows.size()) * row_height;
1687 int32_t required_rows = (height - height_covered) / row_height;
1689 while(required_rows > 0) {
1690 auto new_row = make_row(
state);
1691 row_windows.push_back(new_row.get());
1692 new_row->base_data.position.y += int16_t(height_covered);
1693 add_child_to_back(std::move(new_row));
1695 height_covered += row_height;
1699 visible_row_count = height / row_height;
1700 base_data.size.y = int16_t(row_height * visible_row_count);
1702 if(visible_row_count != 0) {
1703 if(scrollbar_is_internal)
1704 base_data.size.x -= 16;
1705 list_scrollbar->scale_to_parent();
1706 if(scrollbar_is_internal)
1707 base_data.size.x += 16;
1711template<
typename contents_type>
1713 auto ptr = make_element_by_type<listbox2_scrollbar>(
state,
"standardlistbox_slider");
1715 add_child_to_back(std::move(ptr));
1717 auto base_row = make_row(
state);
1718 row_windows.push_back(base_row.get());
1719 add_child_to_back(std::move(base_row));
1721 resize(
state, base_data.size.y);
1723template<
typename contents_type>
1725 dcon::gfx_object_id gid = base_data.data.list_box.background_image;
1727 auto const& gfx_def =
state.ui_defs.gfx[gid];
1728 if(gfx_def.primary_texture_handle) {
1731 float(base_data.size.x),
float(base_data.size.y),
1733 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
1734 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
1737 float(base_data.size.y),
1739 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
1740 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
1744 container_base::render(
state, x, y);
1747template<
class RowWinT,
class RowConT>
1749 int16_t current_y = 0;
1750 int16_t subwindow_y_size = 0;
1751 while(current_y + subwindow_y_size <= base_data.size.y) {
1752 auto ptr = make_element_by_type<RowWinT>(
state, get_row_element_name());
1753 row_windows.push_back(
static_cast<RowWinT*
>(ptr.get()));
1754 int16_t offset = ptr->base_data.position.y;
1755 ptr->base_data.position.y += current_y;
1756 subwindow_y_size = ptr->base_data.size.y;
1757 current_y += ptr->base_data.size.y + offset;
1758 add_child_to_front(std::move(ptr));
1760 auto ptr = make_element_by_type<standard_listbox_scrollbar<RowWinT, RowConT>>(
state,
"standardlistbox_slider");
1762 add_child_to_front(std::move(ptr));
1763 list_scrollbar->scale_to_parent();
1768template<
class RowWinT,
class RowConT>
1770 dcon::gfx_object_id gid = base_data.data.list_box.background_image;
1772 auto const& gfx_def =
state.ui_defs.gfx[gid];
1773 if(gfx_def.primary_texture_handle) {
1776 float(base_data.size.x),
float(base_data.size.y),
1778 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
1779 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
1782 float(base_data.size.y),
1784 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
1785 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
1789 container_base::render(
state, x, y);
1791template<
class ItemWinT,
class ItemConT>
1793 auto spacing = int16_t(base_data.data.overlapping.spacing);
1794 if(base_data.get_element_type() == element_type::overlapping) {
1795 while(row_contents.size() > windows.size()) {
1796 auto ptr = make_element_by_type<ItemWinT>(
state, get_row_element_name());
1797 if(subwindow_width <= 0) {
1798 subwindow_width = ptr->base_data.size.x;
1800 windows.push_back(
static_cast<ItemWinT*
>(ptr.get()));
1801 add_child_to_front(std::move(ptr));
1804 float size_ratio = float(row_contents.size() * (subwindow_width + spacing)) / float(base_data.size.x);
1805 int16_t offset = spacing + subwindow_width;
1806 if(size_ratio > 1.f) {
1807 offset = int16_t(
float(subwindow_width) / size_ratio);
1809 int16_t current_x = 0;
1810 if(base_data.data.overlapping.image_alignment == alignment::right) {
1811 current_x = base_data.size.x - subwindow_width - offset * int16_t(row_contents.size() - 1);
1813 for(
size_t i = 0; i < windows.size(); i++) {
1814 if(i < row_contents.size()) {
1815 update_subwindow(
state, *windows[i], row_contents[i]);
1816 windows[i]->base_data.position.x = current_x;
1817 current_x += offset;
1818 windows[i]->set_visible(
state,
true);
1820 windows[i]->set_visible(
state,
false);
1826std::string_view overlapping_flags_box::get_row_element_name() {
1827 return "flag_list_flag";
1831 dcon::national_identity_id content) {
1836 current_nation = retrieve<dcon::nation_id>(
state, parent);
1837 populate_flags(
state);
1841 if(
bool(current_nation)) {
1842 row_contents.clear();
1843 for(
auto it :
state.world.nation_get_gp_relationship_as_great_power(current_nation)) {
1845 row_contents.push_back(it.get_influence_target().get_identity_from_identity_holder());
1853 if(
bool(current_nation)) {
1854 row_contents.clear();
1855 for(
auto it :
state.world.nation_get_gp_relationship_as_great_power(current_nation)) {
1857 row_contents.push_back(it.get_influence_target().get_identity_from_identity_holder());
1865 if(
bool(current_nation)) {
1866 row_contents.clear();
1867 if(
state.world.nation_get_in_sphere_of(current_nation)) {
1868 row_contents.push_back(
state.world.nation_get_in_sphere_of(current_nation).get_identity_from_identity_holder());
1870 for(
auto it :
state.world.nation_get_gp_relationship_as_great_power(current_nation)) {
1872 row_contents.push_back(it.get_influence_target().get_identity_from_identity_holder());
1880 if(
bool(current_nation)) {
1881 row_contents.clear();
1883 auto overlord =
state.world.nation_get_overlord_as_subject(current_nation);
1885 if(
bool(overlord_nation)) {
1886 row_contents.push_back(overlord_nation.get_identity_from_identity_holder().id);
1888 for(
auto puppet :
state.world.nation_get_overlord_as_ruler(current_nation)) {
1889 row_contents.push_back(puppet.get_subject().get_identity_from_identity_holder().id);
1897 if(
bool(current_nation)) {
1898 row_contents.clear();
1899 for(
auto rel :
state.world.nation_get_diplomatic_relation(current_nation)) {
1900 if(rel.get_are_allied()) {
1903 row_contents.push_back(fat_ally.get_identity_from_identity_holder().id);
1911 if(
bool(current_nation)) {
1912 row_contents.clear();
1913 for(
auto wa :
state.world.nation_get_war_participant(current_nation)) {
1914 bool is_attacker = wa.get_is_attacker();
1915 for(
auto o : wa.get_war().get_war_participant()) {
1916 if(o.get_is_attacker() != is_attacker) {
1917 row_contents.push_back(o.get_nation().get_identity_from_identity_holder().id);
1926std::string_view overlapping_truce_flags::get_row_element_name() {
1927 return "flag_list_flag";
1940 current_nation = retrieve<dcon::nation_id>(
state, parent);
1942 row_contents.clear();
1943 for(
auto rel :
state.world.nation_get_diplomatic_relation(current_nation)) {
1944 if(rel.get_truce_until() &&
state.current_date < rel.get_truce_until()) {
1945 auto other = rel.get_related_nations(0) != current_nation ? rel.get_related_nations(0) : rel.get_related_nations(1);
1947 row_contents.push_back(
truce_pair{ other, rel.get_truce_until() });
1956 auto nation = retrieve<dcon::national_identity_id>(
state, parent);
1960 return state.world.nation_get_identity_from_identity_holder(retrieve<dcon::nation_id>(
state, parent));
1964dcon::rebel_faction_id flag_button::get_current_rebel_faction(
sys::state&
state)
noexcept {
1965 return retrieve<dcon::rebel_faction_id>(
state, parent);
1974 auto nation = fat_id.get_nation_from_identity_holder();
1975 if(
bool(nation.id) && nation.get_owned_province_count() != 0) {
1976 state.open_diplomacy(nation.id);
1981 auto nid = retrieve<dcon::nation_id>(
state,
this);
1982 auto tid = retrieve<dcon::national_identity_id>(
state,
this);
1984 nid =
state.world.national_identity_get_nation_from_identity_holder(tid);
1986 auto rid = retrieve<dcon::rebel_faction_id>(
state,
this);
1988 nid =
state.world.rebel_faction_get_ruler_from_rebellion_within(rid);
1990 if(nid &&
state.world.nation_get_owned_province_count(nid) != 0)
1991 state.open_diplomacy(nid);
1995 auto nid = retrieve<dcon::nation_id>(
state,
this);
2001 auto tid = retrieve<dcon::national_identity_id>(
state,
this);
2007 auto reb_tag =
state.national_definitions.rebel_id;
2012 auto nid = retrieve<dcon::nation_id>(
state,
this);
2019 auto tid = retrieve<dcon::national_identity_id>(
state,
this);
2026 auto rid = retrieve<dcon::rebel_faction_id>(
state,
this);
2036 dcon::gfx_object_id gid;
2037 if(base_data.get_element_type() == element_type::image) {
2038 gid = base_data.data.image.gfx_object;
2039 }
else if(base_data.get_element_type() == element_type::button) {
2040 gid = base_data.data.button.button_image;
2042 if(gid && flag_texture_handle > 0) {
2043 auto const& gfx_def =
state.ui_defs.gfx[gid];
2044 if(gfx_def.type_dependent) {
2046 auto& mask_tex =
state.open_gl.asset_textures[dcon::texture_id(gfx_def.type_dependent - 1)];
2048 float(x) +
float(base_data.size.x - mask_tex.size_x) * 0.5f,
2049 float(y) +
float(base_data.size.y - mask_tex.size_y) * 0.5f,
2050 float(mask_tex.size_x),
2051 float(mask_tex.size_y),
2052 flag_texture_handle, mask_handle, base_data.get_rotation(), gfx_def.is_vertically_flipped(),
2056 float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y), flag_texture_handle, base_data.get_rotation(),
2057 gfx_def.is_vertically_flipped(),
2061 image_element_base::render(
state, x, y);
2069 auto nation = fat_id.get_nation_from_identity_holder();
2071 if(
bool(nation.id) && nation.get_owned_province_count() != 0) {
2080 set_current_nation(
state, get_current_nation(
state));
2084 button_element_base::on_create(
state);
2088 dcon::gfx_object_id gid;
2089 if(base_data.get_element_type() == element_type::image) {
2090 gid = base_data.data.image.gfx_object;
2091 }
else if(base_data.get_element_type() == element_type::button) {
2092 gid = base_data.data.button.button_image;
2094 if(gid && flag_texture_handle > 0) {
2095 auto const& gfx_def =
state.ui_defs.gfx[gid];
2096 if(gfx_def.type_dependent) {
2098 auto& mask_tex =
state.open_gl.asset_textures[dcon::texture_id(gfx_def.type_dependent - 1)];
2100 float(x) +
float(base_data.size.x - mask_tex.size_x) * 0.5f,
2101 float(y) +
float(base_data.size.y - mask_tex.size_y) * 0.5f,
2102 float(mask_tex.size_x),
2103 float(mask_tex.size_y),
2104 flag_texture_handle, mask_handle, base_data.get_rotation(), gfx_def.is_vertically_flipped(),
2108 float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y), flag_texture_handle, base_data.get_rotation(),
2109 gfx_def.is_vertically_flipped(),
2113 image_element_base::render(
state, x, y);
2125 if(
auto reb = get_current_rebel_faction(
state); reb) {
2135 auto p = retrieve<dcon::province_id>(
state, parent);
2136 if(p &&
state.local_player_nation)
2141 auto& def =
state.ui_defs.gui[base_definition];
2150 auto p = retrieve<dcon::province_id>(
state, parent);
2158 auto& def =
state.ui_defs.gui[base_definition];
2164 auto p = retrieve<dcon::province_id>(
state, parent);
2167 if(!
state.local_player_nation)
2170 auto name =
state.to_string_view(def.name);
2171 auto tt_name = std::string{
name } +
"_tooltip";
2172 if(
state.key_is_localized(tt_name)) {
2177 if(def.data.button.scriptable_enable) {
2182 if(def.data.button.scriptable_effect) {
2188 auto n = retrieve<dcon::nation_id>(
state, parent);
2189 if(n &&
state.local_player_nation) {
2191 }
else if(
state.local_player_nation) {
2197 auto& def =
state.ui_defs.gui[base_definition];
2206 auto n = retrieve<dcon::nation_id>(
state, parent);
2207 if(!
state.local_player_nation) {
2214 auto& def =
state.ui_defs.gui[base_definition];
2220 auto n = retrieve<dcon::nation_id>(
state, parent);
2222 n =
state.local_player_nation;
2223 if(!
state.local_player_nation)
2226 auto name =
state.to_string_view(def.name);
2227 auto tt_name = std::string{
name } +
"_tooltip";
2228 if(
state.key_is_localized(tt_name)) {
2233 if(def.data.button.scriptable_enable) {
2238 if(def.data.button.scriptable_effect) {
2245 for(
auto tmp = parent; tmp !=
nullptr; tmp = tmp->parent) {
2246 if(tmp->base_data.get_element_type() == element_type::window && tmp->base_data.data.window.is_moveable()) {
2248 return message_result::consumed;
2251 return message_result::consumed;
2255 auto& def =
state.ui_defs.gui[id];
2257 auto res = std::make_unique<image_element_base>();
2260 res->on_create(
state);
2264 auto res = std::make_unique<province_script_button>(
id);
2267 res->on_create(
state);
2270 auto res = std::make_unique<nation_script_button>(
id);
2273 res->on_create(
state);
2276 auto res = std::make_unique<button_element_base>();
2279 res->on_create(
state);
2283 auto res = std::make_unique<window_element_base>();
2285 res->on_create(
state);
2288 auto res = std::make_unique<scrollbar>();
2290 res->on_create(
state);
2293 auto res = std::make_unique<simple_text_element_base>();
2295 res->on_create(
state);
2324 return message_result::consumed;
2326 return message_result::unseen;
2330 return message_result::consumed;
2332 return message_result::unseen;
2337 int32_t pos_in_track = parent_state.
vertical ? y : x;
2340 if(!parent_state.
vertical &&
state.world.locale_get_native_rtl(
state.font_collection.get_current_locale())) {
2341 fp_pos = 1.f - fp_pos;
2342 assert(fp_pos >= 0.f && fp_pos <= 1.f);
2345 return message_result::consumed;
2350 return parent->has_tooltip(
state);
2351 return opaque_element_base::has_tooltip(
state);
2355 return parent->update_tooltip(
state, x, y, contents);
2356 return opaque_element_base::update_tooltip(
state, x, y, contents);
2361 return message_result::consumed;
2370 if(!(location_abs.y <= oldy && oldy < base_data.size.y + location_abs.y)) {
2374 if(!(location_abs.x <= oldx && oldx < base_data.size.x + location_abs.x)) {
2379 int32_t pos_in_track = 0;
2390 base_data.position.y += int16_t(y - oldy);
2392 pos_in_track = base_data.position.y - parent_settings.
buttons_size / 2;
2394 if(
state.world.locale_get_native_rtl(
state.font_collection.get_current_locale())) {
2395 base_data.position.x += int16_t(oldx - x);
2397 base_data.position.x += int16_t(x - oldx);
2400 pos_in_track = base_data.position.x - parent_settings.
buttons_size / 2;
2405 parent->impl_get(
state, adjustment_payload);
2409 stored_value = settings.using_limits ? std::clamp(v, settings.lower_limit, settings.upper_limit) : std::clamp(v, settings.lower_value, settings.upper_value);
2411 float percentage = float(stored_value - settings.lower_value) / float(settings.upper_value - settings.lower_value);
2412 auto offset = settings.buttons_size + int32_t((settings.track_size - settings.buttons_size) * percentage);
2414 if(settings.vertical)
2415 slider->base_data.position.y = int16_t(offset);
2417 slider->base_data.position.x = int16_t(offset);
2421 float scaling_factor = float(settings.scaling_factor);
2424 scaling_factor = 0.25f;
2426 int32_t rv = std::clamp(int32_t(v * scaling_factor), settings.lower_value, settings.upper_value);
2427 update_raw_value(
state, rv);
2429float scrollbar::scaled_value()
const {
2430 return float(stored_value) / float(settings.scaling_factor);
2432int32_t scrollbar::raw_value()
const {
2433 return stored_value;
2437 settings.lower_limit = settings_s.
lower_limit * settings.scaling_factor;
2438 settings.lower_value = settings_s.
lower_value * settings.scaling_factor;
2439 settings.upper_limit = settings_s.
upper_limit * settings.scaling_factor;
2440 settings.upper_value = settings_s.
upper_value * settings.scaling_factor;
2443 settings.upper_value = std::max(settings.upper_value, settings.lower_value + 1);
2445 if(settings.using_limits) {
2447 right_limit->set_visible(
state, settings.lower_value < settings.lower_limit);
2449 float percentage = float(settings.lower_limit - settings.lower_value) / float(settings.upper_value - settings.lower_value);
2450 auto offset = settings.buttons_size + int32_t((settings.track_size - settings.buttons_size) * percentage);
2451 if(settings.vertical)
2452 right_limit->base_data.position.y = int16_t(offset);
2454 right_limit->base_data.position.x = int16_t(offset);
2457 left_limit->set_visible(
state, settings.upper_value > settings.upper_limit);
2459 float percentage = float(settings.upper_limit - settings.lower_value) / float(settings.upper_value - settings.lower_value);
2460 auto offset = settings.buttons_size + int32_t((settings.track_size - settings.buttons_size) * percentage);
2461 if(settings.vertical)
2462 left_limit->base_data.position.y = int16_t(offset + settings.buttons_size - 10);
2464 left_limit->base_data.position.x = int16_t(offset + settings.buttons_size - 10);
2466 if(stored_value < settings.lower_limit || stored_value > settings.upper_limit) {
2467 update_raw_value(
state, stored_value);
2472 right_limit->set_visible(
state,
false);
2474 left_limit->set_visible(
state,
false);
2475 if(stored_value < settings.lower_value || stored_value > settings.upper_value) {
2476 update_raw_value(
state, stored_value);
2487 if(base_data.get_element_type() == element_type::scrollbar) {
2488 auto step = base_data.data.scrollbar.get_step_size();
2489 settings.scaling_factor = 1;
2491 case step_size::twenty_five:
2493 case step_size::two:
2495 case step_size::one:
2497 case step_size::one_tenth:
2498 settings.scaling_factor = 10;
2500 case step_size::one_hundredth:
2501 settings.scaling_factor = 100;
2503 case step_size::one_thousandth:
2504 settings.scaling_factor = 1000;
2507 settings.lower_value = 0;
2508 settings.upper_value = base_data.data.scrollbar.max_value * settings.scaling_factor;
2509 settings.lower_limit = 0;
2510 settings.upper_limit = settings.upper_value;
2512 settings.vertical = !base_data.data.scrollbar.is_horizontal();
2513 stored_value = settings.lower_value;
2515 auto first_child = base_data.data.scrollbar.first_child;
2516 auto num_children = base_data.data.scrollbar.num_children;
2518 if(num_children >= 6) {
2519 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(5 + first_child.index()));
2520 auto ch_res = make_element_by_type<image_element_base>(
state, child_tag);
2521 right_limit = ch_res.get();
2522 right_limit->set_visible(
state,
false);
2523 add_child_to_back(std::move(ch_res));
2525 if(num_children >= 5) {
2526 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(4 + first_child.index()));
2527 auto ch_res = make_element_by_type<image_element_base>(
state, child_tag);
2528 left_limit = ch_res.get();
2529 left_limit->set_visible(
state,
false);
2530 add_child_to_back(std::move(ch_res));
2533 if(num_children >= 4) {
2535 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(2 + first_child.index()));
2536 auto ch_res = make_element_by_type<scrollbar_slider>(
state, child_tag);
2537 slider = ch_res.get();
2538 add_child_to_back(std::move(ch_res));
2541 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(0 + first_child.index()));
2542 auto ch_res = make_element_by_type<scrollbar_left>(
state, child_tag);
2543 left = ch_res.get();
2544 add_child_to_back(std::move(ch_res));
2546 settings.buttons_size = settings.vertical ?
left->base_data.size.y :
left->base_data.size.x;
2547 if(step_size::twenty_five == step)
2548 left->step_size = 25;
2549 else if(step_size::two == step)
2550 left->step_size = 2;
2552 left->step_size = 1;
2555 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(1 + first_child.index()));
2556 auto ch_res = make_element_by_type<scrollbar_right>(
state, child_tag);
2557 right = ch_res.get();
2558 add_child_to_back(std::move(ch_res));
2560 if(step_size::twenty_five == step)
2561 right->step_size = 25;
2562 else if(step_size::two == step)
2563 right->step_size = 2;
2565 right->step_size = 1;
2568 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(3 + first_child.index()));
2569 auto ch_res = make_element_by_type<scrollbar_track>(
state, child_tag);
2570 track = ch_res.get();
2571 add_child_to_back(std::move(ch_res));
2573 settings.track_size = settings.vertical ? track->base_data.size.y : track->base_data.size.x;
2575 left->base_data.position.x = 0;
2576 left->base_data.position.y = 0;
2577 if(settings.vertical) {
2578 track->base_data.position.y = int16_t(settings.buttons_size);
2579 slider->base_data.position.y = int16_t(settings.buttons_size);
2580 right->base_data.position.y = int16_t(settings.track_size + settings.buttons_size);
2582 slider->base_data.position.x = 0;
2583 right->base_data.position.x = 0;
2585 track->base_data.position.x = int16_t(settings.buttons_size);
2586 slider->base_data.position.x = int16_t(settings.buttons_size);
2587 right->base_data.position.x = int16_t(settings.track_size + settings.buttons_size);
2589 slider->base_data.position.y = 0;
2590 right->base_data.position.y = 0;
2597 parent->impl_on_drag_finish(
state);
2602 settings.track_size = track ? int32_t(settings.vertical ? track->base_data.size.y : track->base_data.size.x) : 1;
2604 return message_result::consumed;
2606 auto adjustments = any_cast<value_change>(payload);
2608 if(adjustments.is_relative)
2609 stored_value += adjustments.new_value;
2611 stored_value = adjustments.new_value;
2613 if(adjustments.move_slider) {
2614 update_raw_value(
state, stored_value);
2616 stored_value = settings.using_limits ? std::clamp(stored_value, settings.lower_limit, settings.upper_limit)
2617 : std::clamp(stored_value, settings.lower_value, settings.upper_value);
2620 if(adjustments.move_slider ==
true && adjustments.is_relative ==
false && !
state.ui_state.
drag_target) {
2624 on_value_change(
state, stored_value);
2625 return message_result::unseen;
2627 return message_result::unseen;
2632 auto display_unit = retrieve< unit_var>(
state, parent);
2633 if(std::holds_alternative<dcon::army_id>(display_unit))
2635 else if(std::holds_alternative<dcon::navy_id>(display_unit))
2648 static const std::string_view key_names[] = {
2653 "Multimedia button",
2791 "Navigation Accept",
2792 "Navigation Cancel",
ANY_ALWAYS_INLINE bool holds_type() const noexcept
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void move_child_to_back(element_base *child) noexcept final
void impl_render(sys::state &state, int32_t x, int32_t y) noexcept override
message_result impl_set(sys::state &state, Cyto::Any &payload) noexcept final
void add_child_to_back(std::unique_ptr< element_base > child) noexcept final
std::unique_ptr< element_base > remove_child(element_base *child) noexcept final
void impl_on_reset_text(sys::state &state) noexcept override
void add_child_to_front(std::unique_ptr< element_base > child) noexcept final
mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
void move_child_to_front(element_base *child) noexcept final
element_base * get_child_by_name(sys::state const &state, std::string_view name) noexcept final
message_result impl_on_key_down(sys::state &state, sys::virtual_key key, sys::key_modifiers mods) noexcept final
void impl_on_update(sys::state &state) noexcept override
element_base * get_child_by_index(sys::state const &state, int32_t index) noexcept final
static constexpr dcon::texture_id small_tiles_dialog
static constexpr dcon::texture_id tiles_dialog
static constexpr dcon::texture_id transparency
void on_update(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
message_result on_key_down(sys::state &state, sys::virtual_key key, sys::key_modifiers mods) noexcept override
void on_reset_text(sys::state &state) noexcept override
message_result on_lbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
static constexpr uint8_t is_invisible_mask
virtual message_result get(sys::state &state, Cyto::Any &payload) noexcept
virtual void impl_render(sys::state &state, int32_t x, int32_t y) noexcept
virtual message_result impl_on_key_down(sys::state &state, sys::virtual_key key, sys::key_modifiers mods) noexcept
virtual void on_create(sys::state &state) noexcept
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
friend void sys::state::on_text(char32_t c)
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void set_data_points(sys::state &state, std::vector< float > const &datapoints) noexcept
message_result on_lbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept override
message_result on_rbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept override
void on_create(sys::state &state) noexcept override
message_result test_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_reset_text(sys::state &state) noexcept override
virtual void populate_tooltip(sys::state &state, T t, float percentage, text::columnar_layout &contents) noexcept
void update_chart(sys::state &state)
void render(sys::state &state, int32_t x, int32_t y) 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
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void on_reset_text(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void set_text(sys::state &state, std::string const &new_text)
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void set_text(sys::state &state, std::string const &new_text)
void on_reset_text(sys::state &state) noexcept override
text::layout internal_layout
void format_text(sys::state &state)
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void on_drag(sys::state &state, int32_t oldx, int32_t oldy, int32_t x, int32_t y, sys::key_modifiers mods) noexcept override
#define assert(condition)
void use_nation_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n)
bool can_use_province_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id p)
void use_province_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id i)
bool can_use_nation_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n)
flag_type get_current_flag_type(sys::state const &state, dcon::nation_id target_nation)
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
constexpr float zoom_very_close
bool are_at_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
constexpr uint8_t level_friendly
constexpr uint8_t level_in_sphere
constexpr uint8_t level_mask
constexpr uint8_t level_cordial
dcon::nation_id get_relationship_partner(sys::state const &state, dcon::diplomatic_relation_id rel_id, dcon::nation_id query)
dcon::text_key name_from_tag(sys::state &state, dcon::national_identity_id tag)
void render_tinted_subsprite(sys::state const &state, int frame, int total_frames, float x, float y, float width, float height, float r, float g, float b, GLuint texture_handle, ui::rotation rot, bool flipped, bool rtl)
void render_bordered_rect(sys::state const &state, color_modification enabled, float border_size, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
void render_piechart(sys::state const &state, color_modification enabled, float x, float y, float size, data_texture &t)
void render_masked_rect(sys::state const &state, color_modification enabled, float x, float y, float width, float height, GLuint texture_handle, GLuint mask_texture_handle, ui::rotation r, bool flipped, bool rtl)
void render_subsprite(sys::state const &state, color_modification enabled, int frame, int total_frames, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
void render_text(sys::state &state, text::stored_glyphs const &txt, color_modification enabled, float x, float y, color3f const &c, uint16_t font_id)
void render_linegraph(sys::state const &state, color_modification enabled, float x, float y, float width, float height, lines &l)
void render_text_flag(sys::state &state, text::embedded_flag ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
void render_textured_rect(sys::state const &state, color_modification enabled, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
GLuint get_texture_handle(sys::state &state, dcon::texture_id id, bool keep_data)
void render_text_icon(sys::state &state, text::embedded_icon ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
void render_tinted_textured_rect(sys::state const &state, float x, float y, float width, float height, float r, float g, float b, GLuint texture_handle, ui::rotation rot, bool flipped, bool rtl)
void render_text_unit_icon(sys::state &state, text::embedded_unit_icon ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
void render_progress_bar(sys::state const &state, color_modification enabled, float progress, float x, float y, float width, float height, GLuint left_texture_handle, GLuint right_texture_handle, ui::rotation r, bool flipped, bool rtl)
GLuint get_flag_handle(sys::state &state, dcon::national_identity_id nat_id, culture::flag_type type)
std::string lowercase_str(std::string_view sv)
std::string rebel_name(sys::state &state, dcon::rebel_faction_id reb)
std::string native_to_utf8(native_string_view data_in)
void play_interface_sound(sys::state &state, audio_instance &s, float volume)
audio_instance & get_click_sound(sys::state &state)
float blue_from_int(uint32_t v)
float green_from_int(uint32_t v)
uint32_t pack_color(float r, float g, float b)
float red_from_int(uint32_t v)
void add_to_layout_box(sys::state &state, layout_base &dest, layout_box &box, embedded_flag ico)
int32_t size_from_font_id(uint16_t id)
layout_box open_layout_box(layout_base &dest, int32_t indent)
bool is_black_from_font_id(uint16_t id)
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
void add_line_break_to_layout(sys::state &state, columnar_layout &dest)
text::alignment to_text_alignment(ui::alignment in)
ankerl::unordered_dense::map< uint32_t, substitution > substitution_map
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
dcon::text_key get_name(sys::state &state, dcon::nation_id id)
font_selection font_index_from_font_id(sys::state &state, uint16_t id)
std::string format_percentage(float num, size_t digits)
void add_space_to_layout_box(sys::state &state, layout_base &dest, layout_box &box)
void close_layout_box(columnar_layout &dest, layout_box &box)
int32_t to_generic(dcon::province_id v)
int32_t ui_height(sys::state const &state)
void make_size_from_graphics(sys::state &state, ui::element_data &dat)
xy_pair child_relative_location(sys::state &state, element_base const &parent, element_base const &child)
uint32_t internal_get_interactable_disabled_color(float r, float g, float b)
uint32_t internal_get_disabled_color(float r, float g, float b)
void effect_description(sys::state &state, text::layout_base &layout, dcon::effect_key k, int32_t primary_slot, int32_t this_slot, int32_t from_slot, uint32_t r_lo, uint32_t r_hi)
int32_t ui_width(sys::state const &state)
void render_text_chunk(sys::state &state, text::text_chunk t, float x, float baseline_y, uint16_t font_id, ogl::color3f text_color, ogl::color_modification cmod)
void populate_shortcut_tooltip(sys::state &state, ui::element_base &elm, text::columnar_layout &contents) noexcept
xy_pair get_absolute_location(sys::state &state, element_base const &node)
void send(sys::state &state, element_base *parent, T value)
void trigger_description(sys::state &state, text::layout_base &layout, dcon::trigger_key k, int32_t primary_slot=-1, int32_t this_slot=-1, int32_t from_slot=-1)
ogl::color3f get_text_color(sys::state &state, text::text_color text_color)
std::unique_ptr< element_base > make_element(sys::state &state, std::string_view name)
ogl::color_modification get_color_modification(bool is_under_mouse, bool is_disabled, bool is_interactable)
std::unique_ptr< element_base > make_element_immediate(sys::state &state, dcon::gui_def_id id)
uint32_t internal_get_interactable_color(float r, float g, float b)
message_result greater_result(message_result a, message_result b)
void single_unit_tooltip(sys::state &state, text::columnar_layout &contents, dcon::army_id a)
std::vector< text_chunk > contents
text::stored_glyphs unicodechars
element_type get_element_type() const
static constexpr uint8_t orientation_mask
union ui::element_data::internal_data data
dcon::gfx_object_id gfx_object
listbox2_row_element * row
std::unique_ptr< element_base > army_group_selector_root
element_base * last_tooltip
std::unique_ptr< element_base > province_details_root
std::unique_ptr< tool_tip > tooltip
std::unique_ptr< element_base > rgos_root
ankerl::unordered_dense::map< dcon::text_key, element_target, hash_text_key > defs_by_name
std::unique_ptr< element_base > root
element_base * edit_target
element_base * province_window
std::unique_ptr< element_base > military_root
element_base * drag_target
element_base * under_mouse
std::unique_ptr< element_base > units_root
alignment get_alignment() const
text_base_data text_common