991 if (!p_open || !*p_open)
return;
993 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
995 if (ImGui::Begin(absl::StrFormat(
"%s Theme Editor",
ICON_MD_PALETTE).c_str(), p_open,
996 ImGuiWindowFlags_MenuBar)) {
999 static float editor_animation_time = 0.0f;
1000 editor_animation_time += ImGui::GetIO().DeltaTime;
1002 ImDrawList* draw_list = ImGui::GetWindowDrawList();
1003 ImVec2 window_pos = ImGui::GetWindowPos();
1004 ImVec2 window_size = ImGui::GetWindowSize();
1008 std::vector<gui::Color> theme_colors = {
1009 current_theme.primary, current_theme.secondary, current_theme.accent,
1010 current_theme.success, current_theme.warning, current_theme.error
1013 for (
size_t i = 0; i < theme_colors.size(); ++i) {
1014 float time_offset = i * 1.0f;
1015 float orbit_radius = 60.0f + i * 8.0f;
1016 float x = window_pos.x + window_size.x * 0.8f + cosf(editor_animation_time * 0.3f + time_offset) * orbit_radius;
1017 float y = window_pos.y + window_size.y * 0.3f + sinf(editor_animation_time * 0.3f + time_offset) * orbit_radius;
1019 float alpha = 0.15f + 0.1f * sinf(editor_animation_time * 1.5f + time_offset);
1020 ImU32 orb_color = ImGui::ColorConvertFloat4ToU32(ImVec4(
1021 theme_colors[i].red, theme_colors[i].green, theme_colors[i].blue, alpha));
1023 float radius = 4.0f + sinf(editor_animation_time * 2.0f + time_offset) * 1.0f;
1024 draw_list->AddCircleFilled(ImVec2(x, y), radius, orb_color);
1028 if (ImGui::BeginMenuBar()) {
1029 if (ImGui::BeginMenu(
"File")) {
1030 if (ImGui::MenuItem(absl::StrFormat(
"%s New Theme",
ICON_MD_ADD).c_str())) {
1036 if (!file_path.empty()) {
1041 if (ImGui::MenuItem(absl::StrFormat(
"%s Save Theme",
ICON_MD_SAVE).c_str())) {
1044 if (!current_file_path.empty()) {
1047 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1052 if (!file_path.empty()) {
1055 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1060 if (ImGui::MenuItem(absl::StrFormat(
"%s Save As...",
ICON_MD_SAVE_AS).c_str())) {
1063 if (!file_path.empty()) {
1066 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1073 if (ImGui::BeginMenu(
"Presets")) {
1074 if (ImGui::MenuItem(
"YAZE Classic")) {
1079 if (!available_themes.empty()) {
1081 for (
const auto& theme_name : available_themes) {
1082 if (ImGui::MenuItem(theme_name.c_str())) {
1090 ImGui::EndMenuBar();
1094 static char theme_name[128];
1095 static char theme_description[256];
1096 static char theme_author[128];
1097 static bool live_preview =
true;
1099 static bool theme_backup_made =
false;
1102 auto apply_live_preview = [&]() {
1104 if (!theme_backup_made) {
1106 theme_backup_made =
true;
1114 ImGui::Checkbox(
"Live Preview", &live_preview);
1116 ImGui::Text(
"| Changes apply immediately when enabled");
1119 static bool prev_live_preview = live_preview;
1120 if (prev_live_preview && !live_preview && theme_backup_made) {
1122 theme_backup_made =
false;
1124 prev_live_preview = live_preview;
1129 if (ImGui::BeginTable(
"ThemeMetadata", 2, ImGuiTableFlags_SizingStretchProp)) {
1130 ImGui::TableSetupColumn(
"Field", ImGuiTableColumnFlags_WidthFixed, 100.0f);
1131 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
1133 ImGui::TableNextRow();
1134 ImGui::TableNextColumn();
1135 ImGui::AlignTextToFramePadding();
1136 ImGui::Text(
"Name:");
1137 ImGui::TableNextColumn();
1138 if (ImGui::InputText(
"##theme_name", theme_name,
sizeof(theme_name))) {
1139 edit_theme.
name = std::string(theme_name);
1142 ImGui::TableNextRow();
1143 ImGui::TableNextColumn();
1144 ImGui::AlignTextToFramePadding();
1145 ImGui::Text(
"Description:");
1146 ImGui::TableNextColumn();
1147 if (ImGui::InputText(
"##theme_description", theme_description,
sizeof(theme_description))) {
1148 edit_theme.
description = std::string(theme_description);
1151 ImGui::TableNextRow();
1152 ImGui::TableNextColumn();
1153 ImGui::AlignTextToFramePadding();
1154 ImGui::Text(
"Author:");
1155 ImGui::TableNextColumn();
1156 if (ImGui::InputText(
"##theme_author", theme_author,
sizeof(theme_author))) {
1157 edit_theme.
author = std::string(theme_author);
1166 if (ImGui::BeginTabBar(
"ThemeEditorTabs", ImGuiTabBarFlags_None)) {
1169 static bool first_frame =
true;
1170 if (first_frame && live_preview) {
1171 apply_live_preview();
1172 first_frame =
false;
1176 if (ImGui::BeginTabItem(absl::StrFormat(
"%s Primary",
ICON_MD_COLOR_LENS).c_str())) {
1177 if (ImGui::BeginTable(
"PrimaryColorsTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1178 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1179 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1180 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1181 ImGui::TableHeadersRow();
1184 ImGui::TableNextRow();
1185 ImGui::TableNextColumn();
1186 ImGui::AlignTextToFramePadding();
1187 ImGui::Text(
"Primary:");
1188 ImGui::TableNextColumn();
1190 if (ImGui::ColorEdit3(
"##primary", &primary.x)) {
1191 edit_theme.
primary = {primary.x, primary.y, primary.z, primary.w};
1192 apply_live_preview();
1194 ImGui::TableNextColumn();
1195 ImGui::Button(
"Primary Preview", ImVec2(-1, 30));
1198 ImGui::TableNextRow();
1199 ImGui::TableNextColumn();
1200 ImGui::AlignTextToFramePadding();
1201 ImGui::Text(
"Secondary:");
1202 ImGui::TableNextColumn();
1204 if (ImGui::ColorEdit3(
"##secondary", &secondary.x)) {
1205 edit_theme.
secondary = {secondary.x, secondary.y, secondary.z, secondary.w};
1206 apply_live_preview();
1208 ImGui::TableNextColumn();
1209 ImGui::PushStyleColor(ImGuiCol_Button, secondary);
1210 ImGui::Button(
"Secondary Preview", ImVec2(-1, 30));
1211 ImGui::PopStyleColor();
1214 ImGui::TableNextRow();
1215 ImGui::TableNextColumn();
1216 ImGui::AlignTextToFramePadding();
1217 ImGui::Text(
"Accent:");
1218 ImGui::TableNextColumn();
1220 if (ImGui::ColorEdit3(
"##accent", &accent.x)) {
1221 edit_theme.
accent = {accent.x, accent.y, accent.z, accent.w};
1222 apply_live_preview();
1224 ImGui::TableNextColumn();
1225 ImGui::PushStyleColor(ImGuiCol_Button, accent);
1226 ImGui::Button(
"Accent Preview", ImVec2(-1, 30));
1227 ImGui::PopStyleColor();
1230 ImGui::TableNextRow();
1231 ImGui::TableNextColumn();
1232 ImGui::AlignTextToFramePadding();
1233 ImGui::Text(
"Background:");
1234 ImGui::TableNextColumn();
1236 if (ImGui::ColorEdit4(
"##background", &background.x)) {
1237 edit_theme.
background = {background.x, background.y, background.z, background.w};
1238 apply_live_preview();
1240 ImGui::TableNextColumn();
1241 ImGui::Text(
"Background preview shown in window");
1245 ImGui::EndTabItem();
1250 if (ImGui::BeginTable(
"TextColorsTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1251 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1252 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1253 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1254 ImGui::TableHeadersRow();
1257 auto text_colors = std::vector<std::pair<const char*, Color*>>{
1268 for (
auto& [label, color_ptr] : text_colors) {
1269 ImGui::TableNextRow();
1270 ImGui::TableNextColumn();
1271 ImGui::AlignTextToFramePadding();
1272 ImGui::Text(
"%s:", label);
1274 ImGui::TableNextColumn();
1276 std::string
id = absl::StrFormat(
"##%s", label);
1277 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1278 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1279 apply_live_preview();
1282 ImGui::TableNextColumn();
1283 ImGui::PushStyleColor(ImGuiCol_Text, color_vec);
1284 ImGui::Text(
"Sample %s", label);
1285 ImGui::PopStyleColor();
1290 ImGui::EndTabItem();
1294 if (ImGui::BeginTabItem(absl::StrFormat(
"%s Interactive",
ICON_MD_TOUCH_APP).c_str())) {
1295 if (ImGui::BeginTable(
"InteractiveColorsTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1296 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1297 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1298 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1299 ImGui::TableHeadersRow();
1302 auto interactive_colors = std::vector<std::tuple<const char*, Color*, ImGuiCol>>{
1303 {
"Button", &edit_theme.
button, ImGuiCol_Button},
1304 {
"Button Hovered", &edit_theme.
button_hovered, ImGuiCol_ButtonHovered},
1305 {
"Button Active", &edit_theme.
button_active, ImGuiCol_ButtonActive},
1306 {
"Frame Background", &edit_theme.
frame_bg, ImGuiCol_FrameBg},
1307 {
"Frame BG Hovered", &edit_theme.
frame_bg_hovered, ImGuiCol_FrameBgHovered},
1308 {
"Frame BG Active", &edit_theme.
frame_bg_active, ImGuiCol_FrameBgActive},
1309 {
"Check Mark", &edit_theme.
check_mark, ImGuiCol_CheckMark},
1310 {
"Slider Grab", &edit_theme.
slider_grab, ImGuiCol_SliderGrab},
1314 for (
auto& [label, color_ptr, imgui_col] : interactive_colors) {
1315 ImGui::TableNextRow();
1316 ImGui::TableNextColumn();
1317 ImGui::AlignTextToFramePadding();
1318 ImGui::Text(
"%s:", label);
1320 ImGui::TableNextColumn();
1322 std::string
id = absl::StrFormat(
"##%s", label);
1323 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1324 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1325 apply_live_preview();
1328 ImGui::TableNextColumn();
1329 ImGui::PushStyleColor(imgui_col, color_vec);
1330 ImGui::Button(absl::StrFormat(
"Preview %s", label).c_str(), ImVec2(-1, 30));
1331 ImGui::PopStyleColor();
1336 ImGui::EndTabItem();
1340 if (ImGui::BeginTabItem(absl::StrFormat(
"%s Style",
ICON_MD_TUNE).c_str())) {
1341 ImGui::Text(
"Rounding and Border Settings:");
1343 if (ImGui::SliderFloat(
"Window Rounding", &edit_theme.
window_rounding, 0.0f, 20.0f)) {
1346 if (ImGui::SliderFloat(
"Frame Rounding", &edit_theme.
frame_rounding, 0.0f, 20.0f)) {
1349 if (ImGui::SliderFloat(
"Scrollbar Rounding", &edit_theme.
scrollbar_rounding, 0.0f, 20.0f)) {
1352 if (ImGui::SliderFloat(
"Tab Rounding", &edit_theme.
tab_rounding, 0.0f, 20.0f)) {
1355 if (ImGui::SliderFloat(
"Grab Rounding", &edit_theme.
grab_rounding, 0.0f, 20.0f)) {
1360 ImGui::Text(
"Border Sizes:");
1362 if (ImGui::SliderFloat(
"Window Border Size", &edit_theme.
window_border_size, 0.0f, 3.0f)) {
1365 if (ImGui::SliderFloat(
"Frame Border Size", &edit_theme.
frame_border_size, 0.0f, 3.0f)) {
1370 ImGui::Text(
"Animation & Effects:");
1376 if (ImGui::SliderFloat(
"Animation Speed", &edit_theme.
animation_speed, 0.1f, 3.0f)) {
1377 apply_live_preview();
1384 ImGui::EndTabItem();
1388 if (ImGui::BeginTabItem(absl::StrFormat(
"%s Navigation",
ICON_MD_NAVIGATION).c_str())) {
1389 if (ImGui::BeginTable(
"NavigationTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1390 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1391 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1392 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1393 ImGui::TableHeadersRow();
1396 auto window_colors = std::vector<std::tuple<const char*, Color*, const char*>>{
1397 {
"Window Background", &edit_theme.
window_bg,
"Main window background"},
1398 {
"Child Background", &edit_theme.
child_bg,
"Child window background"},
1399 {
"Popup Background", &edit_theme.
popup_bg,
"Popup window background"},
1400 {
"Modal Background", &edit_theme.
modal_bg,
"Modal window background"},
1401 {
"Menu Bar BG", &edit_theme.
menu_bar_bg,
"Menu bar background"}
1404 for (
auto& [label, color_ptr, description] : window_colors) {
1405 ImGui::TableNextRow();
1406 ImGui::TableNextColumn();
1407 ImGui::AlignTextToFramePadding();
1408 ImGui::Text(
"%s:", label);
1410 ImGui::TableNextColumn();
1412 std::string
id = absl::StrFormat(
"##window_%s", label);
1413 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1414 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1415 apply_live_preview();
1418 ImGui::TableNextColumn();
1419 ImGui::TextWrapped(
"%s", description);
1428 if (ImGui::CollapsingHeader(
"Headers & Tabs", ImGuiTreeNodeFlags_DefaultOpen)) {
1429 if (ImGui::BeginTable(
"HeaderTabTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1430 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1431 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1432 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1433 ImGui::TableHeadersRow();
1435 auto header_tab_colors = std::vector<std::pair<const char*, Color*>>{
1436 {
"Header", &edit_theme.
header},
1439 {
"Tab", &edit_theme.
tab},
1446 {
"Title Background", &edit_theme.
title_bg},
1451 for (
auto& [label, color_ptr] : header_tab_colors) {
1452 ImGui::TableNextRow();
1453 ImGui::TableNextColumn();
1454 ImGui::AlignTextToFramePadding();
1455 ImGui::Text(
"%s:", label);
1457 ImGui::TableNextColumn();
1459 std::string
id = absl::StrFormat(
"##header_%s", label);
1460 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1461 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1462 apply_live_preview();
1465 ImGui::TableNextColumn();
1466 ImGui::PushStyleColor(ImGuiCol_Button, color_vec);
1467 ImGui::Button(absl::StrFormat(
"Preview %s", label).c_str(), ImVec2(-1, 25));
1468 ImGui::PopStyleColor();
1476 if (ImGui::CollapsingHeader(
"Navigation & Special")) {
1477 if (ImGui::BeginTable(
"NavSpecialTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1478 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1479 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1480 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1481 ImGui::TableHeadersRow();
1483 auto nav_special_colors = std::vector<std::tuple<const char*, Color*, const char*>>{
1484 {
"Nav Cursor", &edit_theme.
nav_cursor,
"Navigation cursor color"},
1488 {
"Drag Drop Target", &edit_theme.
drag_drop_target,
"Drag and drop target highlight"},
1489 {
"Docking Preview", &edit_theme.
docking_preview,
"Docking area preview"},
1490 {
"Docking Empty BG", &edit_theme.
docking_empty_bg,
"Empty docking space background"}
1493 for (
auto& [label, color_ptr, description] : nav_special_colors) {
1494 ImGui::TableNextRow();
1495 ImGui::TableNextColumn();
1496 ImGui::AlignTextToFramePadding();
1497 ImGui::Text(
"%s:", label);
1499 ImGui::TableNextColumn();
1501 std::string
id = absl::StrFormat(
"##nav_%s", label);
1502 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1503 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1504 apply_live_preview();
1507 ImGui::TableNextColumn();
1508 ImGui::TextWrapped(
"%s", description);
1515 ImGui::EndTabItem();
1520 if (ImGui::BeginTable(
"TablesDataTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1521 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1522 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1523 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1524 ImGui::TableHeadersRow();
1526 auto table_colors = std::vector<std::tuple<const char*, Color*, const char*>>{
1527 {
"Table Header BG", &edit_theme.
table_header_bg,
"Table column headers"},
1530 {
"Table Row BG", &edit_theme.
table_row_bg,
"Normal table rows"},
1531 {
"Table Row BG Alt", &edit_theme.
table_row_bg_alt,
"Alternating table rows"},
1532 {
"Tree Lines", &edit_theme.
tree_lines,
"Tree view connection lines"}
1535 for (
auto& [label, color_ptr, description] : table_colors) {
1536 ImGui::TableNextRow();
1537 ImGui::TableNextColumn();
1538 ImGui::AlignTextToFramePadding();
1539 ImGui::Text(
"%s:", label);
1541 ImGui::TableNextColumn();
1543 std::string
id = absl::StrFormat(
"##table_%s", label);
1544 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1545 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1546 apply_live_preview();
1549 ImGui::TableNextColumn();
1550 ImGui::TextWrapped(
"%s", description);
1559 if (ImGui::CollapsingHeader(
"Plots & Graphs")) {
1560 if (ImGui::BeginTable(
"PlotsTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1561 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1562 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1563 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1564 ImGui::TableHeadersRow();
1566 auto plot_colors = std::vector<std::tuple<const char*, Color*, const char*>>{
1567 {
"Plot Lines", &edit_theme.
plot_lines,
"Line plot color"},
1569 {
"Plot Histogram", &edit_theme.
plot_histogram,
"Histogram fill color"},
1573 for (
auto& [label, color_ptr, description] : plot_colors) {
1574 ImGui::TableNextRow();
1575 ImGui::TableNextColumn();
1576 ImGui::AlignTextToFramePadding();
1577 ImGui::Text(
"%s:", label);
1579 ImGui::TableNextColumn();
1581 std::string
id = absl::StrFormat(
"##plot_%s", label);
1582 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1583 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1584 apply_live_preview();
1587 ImGui::TableNextColumn();
1588 ImGui::TextWrapped(
"%s", description);
1595 ImGui::EndTabItem();
1599 if (ImGui::BeginTabItem(absl::StrFormat(
"%s Borders",
ICON_MD_BORDER_ALL).c_str())) {
1600 if (ImGui::BeginTable(
"BordersControlsTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1601 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1602 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1603 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1604 ImGui::TableHeadersRow();
1606 auto border_control_colors = std::vector<std::tuple<const char*, Color*, const char*>>{
1607 {
"Border", &edit_theme.
border,
"General border color"},
1608 {
"Border Shadow", &edit_theme.
border_shadow,
"Border shadow/depth"},
1609 {
"Separator", &edit_theme.
separator,
"Horizontal/vertical separators"},
1611 {
"Separator Active", &edit_theme.
separator_active,
"Separator active/dragged state"},
1612 {
"Scrollbar BG", &edit_theme.
scrollbar_bg,
"Scrollbar track background"},
1613 {
"Scrollbar Grab", &edit_theme.
scrollbar_grab,
"Scrollbar handle"},
1616 {
"Resize Grip", &edit_theme.
resize_grip,
"Window resize grip"},
1621 for (
auto& [label, color_ptr, description] : border_control_colors) {
1622 ImGui::TableNextRow();
1623 ImGui::TableNextColumn();
1624 ImGui::AlignTextToFramePadding();
1625 ImGui::Text(
"%s:", label);
1627 ImGui::TableNextColumn();
1629 std::string
id = absl::StrFormat(
"##border_%s", label);
1630 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1631 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1632 apply_live_preview();
1635 ImGui::TableNextColumn();
1636 ImGui::TextWrapped(
"%s", description);
1642 ImGui::EndTabItem();
1647 ImGui::Text(
"Enhanced semantic colors and editor-specific customization");
1651 if (ImGui::CollapsingHeader(
"Enhanced Semantic Colors", ImGuiTreeNodeFlags_DefaultOpen)) {
1652 if (ImGui::BeginTable(
"EnhancedSemanticTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1653 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1654 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1655 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1656 ImGui::TableHeadersRow();
1658 auto enhanced_colors = std::vector<std::tuple<const char*, Color*, const char*>>{
1659 {
"Code Background", &edit_theme.
code_background,
"Code blocks background"},
1660 {
"Success Light", &edit_theme.
success_light,
"Light success variant"},
1661 {
"Warning Light", &edit_theme.
warning_light,
"Light warning variant"},
1662 {
"Error Light", &edit_theme.
error_light,
"Light error variant"},
1663 {
"Info Light", &edit_theme.
info_light,
"Light info variant"}
1666 for (
auto& [label, color_ptr, description] : enhanced_colors) {
1667 ImGui::TableNextRow();
1668 ImGui::TableNextColumn();
1669 ImGui::AlignTextToFramePadding();
1670 ImGui::Text(
"%s:", label);
1672 ImGui::TableNextColumn();
1674 std::string
id = absl::StrFormat(
"##enhanced_%s", label);
1675 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1676 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1677 apply_live_preview();
1680 ImGui::TableNextColumn();
1681 ImGui::TextWrapped(
"%s", description);
1689 if (ImGui::CollapsingHeader(
"UI State Colors")) {
1690 if (ImGui::BeginTable(
"UIStateTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1691 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1692 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1693 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1694 ImGui::TableHeadersRow();
1697 ImGui::TableNextRow();
1698 ImGui::TableNextColumn();
1699 ImGui::AlignTextToFramePadding();
1700 ImGui::Text(
"Active Selection:");
1701 ImGui::TableNextColumn();
1703 if (ImGui::ColorEdit4(
"##active_selection", &active_selection.x)) {
1704 edit_theme.
active_selection = {active_selection.x, active_selection.y, active_selection.z, active_selection.w};
1705 apply_live_preview();
1707 ImGui::TableNextColumn();
1708 ImGui::TextWrapped(
"Active/selected UI elements");
1710 ImGui::TableNextRow();
1711 ImGui::TableNextColumn();
1712 ImGui::AlignTextToFramePadding();
1713 ImGui::Text(
"Hover Highlight:");
1714 ImGui::TableNextColumn();
1716 if (ImGui::ColorEdit4(
"##hover_highlight", &hover_highlight.x)) {
1717 edit_theme.
hover_highlight = {hover_highlight.x, hover_highlight.y, hover_highlight.z, hover_highlight.w};
1718 apply_live_preview();
1720 ImGui::TableNextColumn();
1721 ImGui::TextWrapped(
"General hover state highlighting");
1723 ImGui::TableNextRow();
1724 ImGui::TableNextColumn();
1725 ImGui::AlignTextToFramePadding();
1726 ImGui::Text(
"Focus Border:");
1727 ImGui::TableNextColumn();
1729 if (ImGui::ColorEdit3(
"##focus_border", &focus_border.x)) {
1730 edit_theme.
focus_border = {focus_border.x, focus_border.y, focus_border.z, focus_border.w};
1731 apply_live_preview();
1733 ImGui::TableNextColumn();
1734 ImGui::TextWrapped(
"Border for focused input elements");
1736 ImGui::TableNextRow();
1737 ImGui::TableNextColumn();
1738 ImGui::AlignTextToFramePadding();
1739 ImGui::Text(
"Disabled Overlay:");
1740 ImGui::TableNextColumn();
1742 if (ImGui::ColorEdit4(
"##disabled_overlay", &disabled_overlay.x)) {
1743 edit_theme.
disabled_overlay = {disabled_overlay.x, disabled_overlay.y, disabled_overlay.z, disabled_overlay.w};
1744 apply_live_preview();
1746 ImGui::TableNextColumn();
1747 ImGui::TextWrapped(
"Semi-transparent overlay for disabled elements");
1754 if (ImGui::CollapsingHeader(
"Editor-Specific Colors")) {
1755 if (ImGui::BeginTable(
"EditorColorsTable", 3, ImGuiTableFlags_SizingStretchProp)) {
1756 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed, 120.0f);
1757 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch, 0.6f);
1758 ImGui::TableSetupColumn(
"Description", ImGuiTableColumnFlags_WidthStretch, 0.4f);
1759 ImGui::TableHeadersRow();
1761 auto editor_colors = std::vector<std::tuple<const char*, Color*, const char*, bool>>{
1762 {
"Editor Background", &edit_theme.
editor_background,
"Main editor canvas background",
false},
1763 {
"Editor Grid", &edit_theme.
editor_grid,
"Grid lines in map/graphics editors",
true},
1764 {
"Editor Cursor", &edit_theme.
editor_cursor,
"Cursor color in editors",
false},
1765 {
"Editor Selection", &edit_theme.
editor_selection,
"Selection highlight in editors",
true}
1768 for (
auto& [label, color_ptr, description, use_alpha] : editor_colors) {
1769 ImGui::TableNextRow();
1770 ImGui::TableNextColumn();
1771 ImGui::AlignTextToFramePadding();
1772 ImGui::Text(
"%s:", label);
1774 ImGui::TableNextColumn();
1776 std::string
id = absl::StrFormat(
"##editor_%s", label);
1777 if (use_alpha ? ImGui::ColorEdit4(
id.c_str(), &color_vec.x) : ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1778 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1779 apply_live_preview();
1782 ImGui::TableNextColumn();
1783 ImGui::TextWrapped(
"%s", description);
1790 ImGui::EndTabItem();
1798 if (ImGui::Button(
"Preview Theme")) {
1803 if (ImGui::Button(
"Reset to Current")) {
1808 theme_name[name_len] =
'\0';
1812 theme_description[desc_len] =
'\0';
1816 theme_author[author_len] =
'\0';
1819 if (theme_backup_made) {
1820 theme_backup_made =
false;
1826 if (ImGui::Button(
"Save Theme")) {
1827 edit_theme.
name = std::string(theme_name);
1828 edit_theme.
description = std::string(theme_description);
1829 edit_theme.
author = std::string(theme_author);
1836 theme_backup_made =
false;
1843 bool can_save_over = !current_file_path.empty();
1845 if (!can_save_over) {
1846 ImGui::BeginDisabled();
1849 if (ImGui::Button(
"Save Over Current")) {
1850 edit_theme.
name = std::string(theme_name);
1851 edit_theme.
description = std::string(theme_description);
1852 edit_theme.
author = std::string(theme_author);
1859 theme_backup_made =
false;
1861 LOG_ERROR(
"Theme Manager",
"Failed to save over current theme");
1865 if (!can_save_over) {
1866 ImGui::EndDisabled();
1869 if (ImGui::IsItemHovered() && can_save_over) {
1870 ImGui::BeginTooltip();
1871 ImGui::Text(
"Save over current theme file:");
1872 ImGui::Text(
"%s", current_file_path.c_str());
1873 ImGui::EndTooltip();
1874 }
else if (ImGui::IsItemHovered()) {
1875 ImGui::BeginTooltip();
1876 ImGui::Text(
"No current theme file to overwrite");
1877 ImGui::Text(
"Use 'Save to File...' to create a new theme file");
1878 ImGui::EndTooltip();
1882 if (ImGui::Button(
"Save to File...")) {
1883 edit_theme.
name = std::string(theme_name);
1884 edit_theme.
description = std::string(theme_description);
1885 edit_theme.
author = std::string(theme_author);
1888 std::string safe_name = edit_theme.
name.empty() ?
"custom_theme" : edit_theme.
name;
1891 if (!file_path.empty()) {
1893 if (file_path.find(
".theme") == std::string::npos) {
1894 file_path +=
".theme";
1903 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1908 if (ImGui::IsItemHovered()) {
1909 ImGui::BeginTooltip();
1910 ImGui::Text(
"Save theme to a .theme file");
1911 ImGui::Text(
"Saved themes can be shared and loaded later");
1912 ImGui::EndTooltip();