1288 if (!p_open || !*p_open)
1291 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
1293 if (ImGui::Begin(absl::StrFormat(
"%s Theme Editor",
ICON_MD_PALETTE).c_str(),
1294 p_open, ImGuiWindowFlags_MenuBar)) {
1296 static float editor_animation_time = 0.0f;
1297 editor_animation_time += ImGui::GetIO().DeltaTime;
1299 ImDrawList* draw_list = ImGui::GetWindowDrawList();
1300 ImVec2 window_pos = ImGui::GetWindowPos();
1301 ImVec2 window_size = ImGui::GetWindowSize();
1305 std::vector<gui::Color> theme_colors = {
1306 current_theme.primary, current_theme.secondary, current_theme.accent,
1307 current_theme.success, current_theme.warning, current_theme.error};
1309 for (
size_t i = 0; i < theme_colors.size(); ++i) {
1310 float time_offset = i * 1.0f;
1311 float orbit_radius = 60.0f + i * 8.0f;
1312 float x = window_pos.x + window_size.x * 0.8f +
1313 cosf(editor_animation_time * 0.3f + time_offset) * orbit_radius;
1314 float y = window_pos.y + window_size.y * 0.3f +
1315 sinf(editor_animation_time * 0.3f + time_offset) * orbit_radius;
1318 0.15f + 0.1f * sinf(editor_animation_time * 1.5f + time_offset);
1319 ImU32 orb_color = ImGui::ColorConvertFloat4ToU32(
1320 ImVec4(theme_colors[i].red, theme_colors[i].green,
1321 theme_colors[i].blue, alpha));
1324 4.0f + sinf(editor_animation_time * 2.0f + time_offset) * 1.0f;
1325 draw_list->AddCircleFilled(ImVec2(x, y), radius, orb_color);
1329 if (ImGui::BeginMenuBar()) {
1330 if (ImGui::BeginMenu(
"File")) {
1331 if (ImGui::MenuItem(
1332 absl::StrFormat(
"%s New Theme",
ICON_MD_ADD).c_str())) {
1336 if (ImGui::MenuItem(
1340 if (!file_path.empty()) {
1345 if (ImGui::MenuItem(
1346 absl::StrFormat(
"%s Save Theme",
ICON_MD_SAVE).c_str())) {
1349 if (!current_file_path.empty()) {
1352 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1358 if (!file_path.empty()) {
1361 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1366 if (ImGui::MenuItem(
1371 if (!file_path.empty()) {
1374 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1381 if (ImGui::BeginMenu(
"Presets")) {
1382 if (ImGui::MenuItem(
"YAZE Classic")) {
1387 if (!available_themes.empty()) {
1389 for (
const auto& theme_name : available_themes) {
1390 if (ImGui::MenuItem(theme_name.c_str())) {
1398 ImGui::EndMenuBar();
1402 static char theme_name[128];
1403 static char theme_description[256];
1404 static char theme_author[128];
1405 static bool live_preview =
true;
1408 static bool theme_backup_made =
false;
1411 auto apply_live_preview = [&]() {
1413 if (!theme_backup_made) {
1415 theme_backup_made =
true;
1424 ImGui::Checkbox(
"Live Preview", &live_preview);
1426 ImGui::Text(
"| Changes apply immediately when enabled");
1429 static bool prev_live_preview = live_preview;
1430 if (prev_live_preview && !live_preview && theme_backup_made) {
1432 theme_backup_made =
false;
1434 prev_live_preview = live_preview;
1439 if (ImGui::BeginTable(
"ThemeMetadata", 2,
1440 ImGuiTableFlags_SizingStretchProp)) {
1441 ImGui::TableSetupColumn(
"Field", ImGuiTableColumnFlags_WidthFixed,
1443 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
1445 ImGui::TableNextRow();
1446 ImGui::TableNextColumn();
1447 ImGui::AlignTextToFramePadding();
1448 ImGui::Text(
"Name:");
1449 ImGui::TableNextColumn();
1450 if (ImGui::InputText(
"##theme_name", theme_name,
sizeof(theme_name))) {
1451 edit_theme.
name = std::string(theme_name);
1454 ImGui::TableNextRow();
1455 ImGui::TableNextColumn();
1456 ImGui::AlignTextToFramePadding();
1457 ImGui::Text(
"Description:");
1458 ImGui::TableNextColumn();
1459 if (ImGui::InputText(
"##theme_description", theme_description,
1460 sizeof(theme_description))) {
1461 edit_theme.
description = std::string(theme_description);
1464 ImGui::TableNextRow();
1465 ImGui::TableNextColumn();
1466 ImGui::AlignTextToFramePadding();
1467 ImGui::Text(
"Author:");
1468 ImGui::TableNextColumn();
1469 if (ImGui::InputText(
"##theme_author", theme_author,
1470 sizeof(theme_author))) {
1471 edit_theme.
author = std::string(theme_author);
1480 if (ImGui::BeginTabBar(
"ThemeEditorTabs", ImGuiTabBarFlags_None)) {
1482 static bool first_frame =
true;
1483 if (first_frame && live_preview) {
1484 apply_live_preview();
1485 first_frame =
false;
1489 if (ImGui::BeginTabItem(
1491 if (ImGui::BeginTable(
"PrimaryColorsTable", 3,
1492 ImGuiTableFlags_SizingStretchProp)) {
1493 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
1495 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1497 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
1499 ImGui::TableHeadersRow();
1502 ImGui::TableNextRow();
1503 ImGui::TableNextColumn();
1504 ImGui::AlignTextToFramePadding();
1505 ImGui::Text(
"Primary:");
1506 ImGui::TableNextColumn();
1508 if (ImGui::ColorEdit3(
"##primary", &primary.x)) {
1509 edit_theme.
primary = {primary.x, primary.y, primary.z, primary.w};
1510 apply_live_preview();
1512 ImGui::TableNextColumn();
1513 ImGui::Button(
"Primary Preview", ImVec2(-1, 30));
1516 ImGui::TableNextRow();
1517 ImGui::TableNextColumn();
1518 ImGui::AlignTextToFramePadding();
1519 ImGui::Text(
"Secondary:");
1520 ImGui::TableNextColumn();
1522 if (ImGui::ColorEdit3(
"##secondary", &secondary.x)) {
1523 edit_theme.
secondary = {secondary.x, secondary.y, secondary.z,
1525 apply_live_preview();
1527 ImGui::TableNextColumn();
1528 ImGui::PushStyleColor(ImGuiCol_Button, secondary);
1529 ImGui::Button(
"Secondary Preview", ImVec2(-1, 30));
1530 ImGui::PopStyleColor();
1533 ImGui::TableNextRow();
1534 ImGui::TableNextColumn();
1535 ImGui::AlignTextToFramePadding();
1536 ImGui::Text(
"Accent:");
1537 ImGui::TableNextColumn();
1539 if (ImGui::ColorEdit3(
"##accent", &accent.x)) {
1540 edit_theme.
accent = {accent.x, accent.y, accent.z, accent.w};
1541 apply_live_preview();
1543 ImGui::TableNextColumn();
1544 ImGui::PushStyleColor(ImGuiCol_Button, accent);
1545 ImGui::Button(
"Accent Preview", ImVec2(-1, 30));
1546 ImGui::PopStyleColor();
1549 ImGui::TableNextRow();
1550 ImGui::TableNextColumn();
1551 ImGui::AlignTextToFramePadding();
1552 ImGui::Text(
"Background:");
1553 ImGui::TableNextColumn();
1555 if (ImGui::ColorEdit4(
"##background", &background.x)) {
1556 edit_theme.
background = {background.x, background.y, background.z,
1558 apply_live_preview();
1560 ImGui::TableNextColumn();
1561 ImGui::Text(
"Background preview shown in window");
1565 ImGui::EndTabItem();
1569 if (ImGui::BeginTabItem(
1571 if (ImGui::BeginTable(
"TextColorsTable", 3,
1572 ImGuiTableFlags_SizingStretchProp)) {
1573 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
1575 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1577 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
1579 ImGui::TableHeadersRow();
1582 auto text_colors = std::vector<std::pair<const char*, Color*>>{
1592 for (
auto& [label, color_ptr] : text_colors) {
1593 ImGui::TableNextRow();
1594 ImGui::TableNextColumn();
1595 ImGui::AlignTextToFramePadding();
1596 ImGui::Text(
"%s:", label);
1598 ImGui::TableNextColumn();
1600 std::string
id = absl::StrFormat(
"##%s", label);
1601 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1602 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1603 apply_live_preview();
1606 ImGui::TableNextColumn();
1607 ImGui::PushStyleColor(ImGuiCol_Text, color_vec);
1608 ImGui::Text(
"Sample %s", label);
1609 ImGui::PopStyleColor();
1614 ImGui::EndTabItem();
1618 if (ImGui::BeginTabItem(
1620 if (ImGui::BeginTable(
"InteractiveColorsTable", 3,
1621 ImGuiTableFlags_SizingStretchProp)) {
1622 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1624 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1626 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
1628 ImGui::TableHeadersRow();
1631 auto interactive_colors =
1632 std::vector<std::tuple<const char*, Color*, ImGuiCol>>{
1633 {
"Button", &edit_theme.
button, ImGuiCol_Button},
1635 ImGuiCol_ButtonHovered},
1637 ImGuiCol_ButtonActive},
1638 {
"Frame Background", &edit_theme.
frame_bg, ImGuiCol_FrameBg},
1640 ImGuiCol_FrameBgHovered},
1642 ImGuiCol_FrameBgActive},
1643 {
"Check Mark", &edit_theme.
check_mark, ImGuiCol_CheckMark},
1644 {
"Slider Grab", &edit_theme.
slider_grab, ImGuiCol_SliderGrab},
1646 ImGuiCol_SliderGrabActive}};
1648 for (
auto& [label, color_ptr, imgui_col] : interactive_colors) {
1649 ImGui::TableNextRow();
1650 ImGui::TableNextColumn();
1651 ImGui::AlignTextToFramePadding();
1652 ImGui::Text(
"%s:", label);
1654 ImGui::TableNextColumn();
1656 std::string
id = absl::StrFormat(
"##%s", label);
1657 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1658 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1659 apply_live_preview();
1662 ImGui::TableNextColumn();
1663 ImGui::PushStyleColor(imgui_col, color_vec);
1664 ImGui::Button(absl::StrFormat(
"Preview %s", label).c_str(),
1666 ImGui::PopStyleColor();
1671 ImGui::EndTabItem();
1675 if (ImGui::BeginTabItem(
1677 ImGui::Text(
"Rounding and Border Settings:");
1679 if (ImGui::SliderFloat(
"Window Rounding", &edit_theme.
window_rounding,
1684 if (ImGui::SliderFloat(
"Frame Rounding", &edit_theme.
frame_rounding,
1689 if (ImGui::SliderFloat(
"Scrollbar Rounding",
1694 if (ImGui::SliderFloat(
"Tab Rounding", &edit_theme.
tab_rounding, 0.0f,
1699 if (ImGui::SliderFloat(
"Grab Rounding", &edit_theme.
grab_rounding, 0.0f,
1706 ImGui::Text(
"Border Sizes:");
1708 if (ImGui::SliderFloat(
"Window Border Size",
1713 if (ImGui::SliderFloat(
"Frame Border Size",
1720 ImGui::Text(
"Animation & Effects:");
1722 if (ImGui::Checkbox(
"Enable Animations",
1728 if (ImGui::SliderFloat(
"Animation Speed", &edit_theme.
animation_speed,
1730 apply_live_preview();
1733 if (ImGui::Checkbox(
"Enable Glow Effects",
1739 ImGui::EndTabItem();
1743 if (ImGui::BeginTabItem(
1745 if (ImGui::BeginTable(
"NavigationTable", 3,
1746 ImGuiTableFlags_SizingStretchProp)) {
1747 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1749 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1751 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
1753 ImGui::TableHeadersRow();
1756 auto window_colors =
1757 std::vector<std::tuple<const char*, Color*, const char*>>{
1758 {
"Window Background", &edit_theme.
window_bg,
1759 "Main window background"},
1760 {
"Child Background", &edit_theme.
child_bg,
1761 "Child window background"},
1762 {
"Popup Background", &edit_theme.
popup_bg,
1763 "Popup window background"},
1764 {
"Modal Background", &edit_theme.
modal_bg,
1765 "Modal window background"},
1767 "Menu bar background"}};
1769 for (
auto& [label, color_ptr, description] : window_colors) {
1770 ImGui::TableNextRow();
1771 ImGui::TableNextColumn();
1772 ImGui::AlignTextToFramePadding();
1773 ImGui::Text(
"%s:", label);
1775 ImGui::TableNextColumn();
1777 std::string
id = absl::StrFormat(
"##window_%s", label);
1778 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1779 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1780 apply_live_preview();
1783 ImGui::TableNextColumn();
1784 ImGui::TextWrapped(
"%s", description);
1793 if (ImGui::CollapsingHeader(
"Headers & Tabs",
1794 ImGuiTreeNodeFlags_DefaultOpen)) {
1795 if (ImGui::BeginTable(
"HeaderTabTable", 3,
1796 ImGuiTableFlags_SizingStretchProp)) {
1797 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1799 ImGui::TableSetupColumn(
"Picker",
1800 ImGuiTableColumnFlags_WidthStretch, 0.6f);
1801 ImGui::TableSetupColumn(
"Preview",
1802 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1803 ImGui::TableHeadersRow();
1805 auto header_tab_colors =
1806 std::vector<std::pair<const char*, Color*>>{
1807 {
"Header", &edit_theme.
header},
1810 {
"Tab", &edit_theme.
tab},
1817 {
"Title Background", &edit_theme.
title_bg},
1821 for (
auto& [label, color_ptr] : header_tab_colors) {
1822 ImGui::TableNextRow();
1823 ImGui::TableNextColumn();
1824 ImGui::AlignTextToFramePadding();
1825 ImGui::Text(
"%s:", label);
1827 ImGui::TableNextColumn();
1829 std::string
id = absl::StrFormat(
"##header_%s", label);
1830 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1831 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
1833 apply_live_preview();
1836 ImGui::TableNextColumn();
1837 ImGui::PushStyleColor(ImGuiCol_Button, color_vec);
1838 ImGui::Button(absl::StrFormat(
"Preview %s", label).c_str(),
1840 ImGui::PopStyleColor();
1848 if (ImGui::CollapsingHeader(
"Navigation & Special")) {
1849 if (ImGui::BeginTable(
"NavSpecialTable", 3,
1850 ImGuiTableFlags_SizingStretchProp)) {
1851 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1853 ImGui::TableSetupColumn(
"Picker",
1854 ImGuiTableColumnFlags_WidthStretch, 0.6f);
1855 ImGui::TableSetupColumn(
"Description",
1856 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1857 ImGui::TableHeadersRow();
1859 auto nav_special_colors =
1860 std::vector<std::tuple<const char*, Color*, const char*>>{
1862 "Navigation cursor color"},
1864 "Window selection highlight"},
1866 "Background dimming for navigation"},
1868 "Background dimming for modals"},
1870 "Drag and drop target highlight"},
1872 "Docking area preview"},
1874 "Empty docking space background"}};
1876 for (
auto& [label, color_ptr, description] : nav_special_colors) {
1877 ImGui::TableNextRow();
1878 ImGui::TableNextColumn();
1879 ImGui::AlignTextToFramePadding();
1880 ImGui::Text(
"%s:", label);
1882 ImGui::TableNextColumn();
1884 std::string
id = absl::StrFormat(
"##nav_%s", label);
1885 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1886 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
1888 apply_live_preview();
1891 ImGui::TableNextColumn();
1892 ImGui::TextWrapped(
"%s", description);
1899 ImGui::EndTabItem();
1903 if (ImGui::BeginTabItem(
1905 if (ImGui::BeginTable(
"TablesDataTable", 3,
1906 ImGuiTableFlags_SizingStretchProp)) {
1907 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1909 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1911 ImGui::TableSetupColumn(
"Description",
1912 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1913 ImGui::TableHeadersRow();
1916 std::vector<std::tuple<const char*, Color*, const char*>>{
1918 "Table column headers"},
1920 "Outer table borders"},
1922 "Inner table borders"},
1924 "Normal table rows"},
1926 "Alternating table rows"},
1928 "Tree view connection lines"}};
1930 for (
auto& [label, color_ptr, description] : table_colors) {
1931 ImGui::TableNextRow();
1932 ImGui::TableNextColumn();
1933 ImGui::AlignTextToFramePadding();
1934 ImGui::Text(
"%s:", label);
1936 ImGui::TableNextColumn();
1938 std::string
id = absl::StrFormat(
"##table_%s", label);
1939 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1940 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1941 apply_live_preview();
1944 ImGui::TableNextColumn();
1945 ImGui::TextWrapped(
"%s", description);
1954 if (ImGui::CollapsingHeader(
"Plots & Graphs")) {
1955 if (ImGui::BeginTable(
"PlotsTable", 3,
1956 ImGuiTableFlags_SizingStretchProp)) {
1957 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1959 ImGui::TableSetupColumn(
"Picker",
1960 ImGuiTableColumnFlags_WidthStretch, 0.6f);
1961 ImGui::TableSetupColumn(
"Description",
1962 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1963 ImGui::TableHeadersRow();
1966 std::vector<std::tuple<const char*, Color*, const char*>>{
1967 {
"Plot Lines", &edit_theme.
plot_lines,
"Line plot color"},
1969 "Line plot hover color"},
1971 "Histogram fill color"},
1972 {
"Plot Histogram Hovered",
1974 "Histogram hover color"}};
1976 for (
auto& [label, color_ptr, description] : plot_colors) {
1977 ImGui::TableNextRow();
1978 ImGui::TableNextColumn();
1979 ImGui::AlignTextToFramePadding();
1980 ImGui::Text(
"%s:", label);
1982 ImGui::TableNextColumn();
1984 std::string
id = absl::StrFormat(
"##plot_%s", label);
1985 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1986 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
1988 apply_live_preview();
1991 ImGui::TableNextColumn();
1992 ImGui::TextWrapped(
"%s", description);
1999 ImGui::EndTabItem();
2003 if (ImGui::BeginTabItem(
2005 if (ImGui::BeginTable(
"BordersControlsTable", 3,
2006 ImGuiTableFlags_SizingStretchProp)) {
2007 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2009 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
2011 ImGui::TableSetupColumn(
"Description",
2012 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2013 ImGui::TableHeadersRow();
2015 auto border_control_colors =
2016 std::vector<std::tuple<const char*, Color*, const char*>>{
2017 {
"Border", &edit_theme.
border,
"General border color"},
2019 "Border shadow/depth"},
2021 "Horizontal/vertical separators"},
2023 "Separator hover state"},
2025 "Separator active/dragged state"},
2027 "Scrollbar track background"},
2029 "Scrollbar handle"},
2031 "Scrollbar handle hover"},
2033 "Scrollbar handle active"},
2035 "Window resize grip"},
2037 "Resize grip hover"},
2039 "Resize grip active"}};
2041 for (
auto& [label, color_ptr, description] : border_control_colors) {
2042 ImGui::TableNextRow();
2043 ImGui::TableNextColumn();
2044 ImGui::AlignTextToFramePadding();
2045 ImGui::Text(
"%s:", label);
2047 ImGui::TableNextColumn();
2049 std::string
id = absl::StrFormat(
"##border_%s", label);
2050 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
2051 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
2052 apply_live_preview();
2055 ImGui::TableNextColumn();
2056 ImGui::TextWrapped(
"%s", description);
2062 ImGui::EndTabItem();
2066 if (ImGui::BeginTabItem(
2069 "Enhanced semantic colors and editor-specific customization");
2073 if (ImGui::CollapsingHeader(
"Enhanced Semantic Colors",
2074 ImGuiTreeNodeFlags_DefaultOpen)) {
2075 if (ImGui::BeginTable(
"EnhancedSemanticTable", 3,
2076 ImGuiTableFlags_SizingStretchProp)) {
2077 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
2079 ImGui::TableSetupColumn(
"Picker",
2080 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2081 ImGui::TableSetupColumn(
"Description",
2082 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2083 ImGui::TableHeadersRow();
2085 auto enhanced_colors =
2086 std::vector<std::tuple<const char*, Color*, const char*>>{
2088 "Code blocks background"},
2090 "Light success variant"},
2092 "Light warning variant"},
2094 "Light error variant"},
2096 "Light info variant"}};
2098 for (
auto& [label, color_ptr, description] : enhanced_colors) {
2099 ImGui::TableNextRow();
2100 ImGui::TableNextColumn();
2101 ImGui::AlignTextToFramePadding();
2102 ImGui::Text(
"%s:", label);
2104 ImGui::TableNextColumn();
2106 std::string
id = absl::StrFormat(
"##enhanced_%s", label);
2107 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
2108 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
2110 apply_live_preview();
2113 ImGui::TableNextColumn();
2114 ImGui::TextWrapped(
"%s", description);
2122 if (ImGui::CollapsingHeader(
"UI State Colors")) {
2123 if (ImGui::BeginTable(
"UIStateTable", 3,
2124 ImGuiTableFlags_SizingStretchProp)) {
2125 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
2127 ImGui::TableSetupColumn(
"Picker",
2128 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2129 ImGui::TableSetupColumn(
"Description",
2130 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2131 ImGui::TableHeadersRow();
2134 ImGui::TableNextRow();
2135 ImGui::TableNextColumn();
2136 ImGui::AlignTextToFramePadding();
2137 ImGui::Text(
"Active Selection:");
2138 ImGui::TableNextColumn();
2139 ImVec4 active_selection =
2141 if (ImGui::ColorEdit4(
"##active_selection", &active_selection.x)) {
2143 active_selection.x, active_selection.y, active_selection.z,
2144 active_selection.w};
2145 apply_live_preview();
2147 ImGui::TableNextColumn();
2148 ImGui::TextWrapped(
"Active/selected UI elements");
2150 ImGui::TableNextRow();
2151 ImGui::TableNextColumn();
2152 ImGui::AlignTextToFramePadding();
2153 ImGui::Text(
"Hover Highlight:");
2154 ImGui::TableNextColumn();
2155 ImVec4 hover_highlight =
2157 if (ImGui::ColorEdit4(
"##hover_highlight", &hover_highlight.x)) {
2159 hover_highlight.x, hover_highlight.y, hover_highlight.z,
2161 apply_live_preview();
2163 ImGui::TableNextColumn();
2164 ImGui::TextWrapped(
"General hover state highlighting");
2166 ImGui::TableNextRow();
2167 ImGui::TableNextColumn();
2168 ImGui::AlignTextToFramePadding();
2169 ImGui::Text(
"Focus Border:");
2170 ImGui::TableNextColumn();
2172 if (ImGui::ColorEdit3(
"##focus_border", &focus_border.x)) {
2173 edit_theme.
focus_border = {focus_border.x, focus_border.y,
2174 focus_border.z, focus_border.w};
2175 apply_live_preview();
2177 ImGui::TableNextColumn();
2178 ImGui::TextWrapped(
"Border for focused input elements");
2180 ImGui::TableNextRow();
2181 ImGui::TableNextColumn();
2182 ImGui::AlignTextToFramePadding();
2183 ImGui::Text(
"Disabled Overlay:");
2184 ImGui::TableNextColumn();
2185 ImVec4 disabled_overlay =
2187 if (ImGui::ColorEdit4(
"##disabled_overlay", &disabled_overlay.x)) {
2189 disabled_overlay.x, disabled_overlay.y, disabled_overlay.z,
2190 disabled_overlay.w};
2191 apply_live_preview();
2193 ImGui::TableNextColumn();
2195 "Semi-transparent overlay for disabled elements");
2202 if (ImGui::CollapsingHeader(
"Editor-Specific Colors")) {
2203 if (ImGui::BeginTable(
"EditorColorsTable", 3,
2204 ImGuiTableFlags_SizingStretchProp)) {
2205 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
2207 ImGui::TableSetupColumn(
"Picker",
2208 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2209 ImGui::TableSetupColumn(
"Description",
2210 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2211 ImGui::TableHeadersRow();
2213 auto editor_colors =
2214 std::vector<std::tuple<const char*, Color*, const char*, bool>>{
2216 "Main editor canvas background",
false},
2218 "Grid lines in map/graphics editors",
true},
2220 "Cursor color in editors",
false},
2222 "Selection highlight in editors",
true}};
2224 for (
auto& [label, color_ptr, description, use_alpha] :
2226 ImGui::TableNextRow();
2227 ImGui::TableNextColumn();
2228 ImGui::AlignTextToFramePadding();
2229 ImGui::Text(
"%s:", label);
2231 ImGui::TableNextColumn();
2233 std::string
id = absl::StrFormat(
"##editor_%s", label);
2234 if (use_alpha ? ImGui::ColorEdit4(
id.c_str(), &color_vec.x)
2235 : ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
2236 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
2238 apply_live_preview();
2241 ImGui::TableNextColumn();
2242 ImGui::TextWrapped(
"%s", description);
2249 ImGui::EndTabItem();
2257 if (ImGui::Button(
"Preview Theme")) {
2262 if (ImGui::Button(
"Reset to Current")) {
2268 theme_name[name_len] =
'\0';
2271 sizeof(theme_description) - 1);
2274 theme_description[desc_len] =
'\0';
2279 theme_author[author_len] =
'\0';
2282 if (theme_backup_made) {
2283 theme_backup_made =
false;
2290 if (ImGui::Button(
"Save Theme")) {
2291 edit_theme.
name = std::string(theme_name);
2292 edit_theme.
description = std::string(theme_description);
2293 edit_theme.
author = std::string(theme_author);
2300 theme_backup_made =
false;
2307 bool can_save_over = !current_file_path.empty();
2309 if (!can_save_over) {
2310 ImGui::BeginDisabled();
2313 if (ImGui::Button(
"Save Over Current")) {
2314 edit_theme.
name = std::string(theme_name);
2315 edit_theme.
description = std::string(theme_description);
2316 edit_theme.
author = std::string(theme_author);
2326 LOG_ERROR(
"Theme Manager",
"Failed to save over current theme");
2330 if (!can_save_over) {
2331 ImGui::EndDisabled();
2334 if (ImGui::IsItemHovered() && can_save_over) {
2335 ImGui::BeginTooltip();
2336 ImGui::Text(
"Save over current theme file:");
2337 ImGui::Text(
"%s", current_file_path.c_str());
2338 ImGui::EndTooltip();
2339 }
else if (ImGui::IsItemHovered()) {
2340 ImGui::BeginTooltip();
2341 ImGui::Text(
"No current theme file to overwrite");
2342 ImGui::Text(
"Use 'Save to File...' to create a new theme file");
2343 ImGui::EndTooltip();
2347 if (ImGui::Button(
"Save to File...")) {
2348 edit_theme.
name = std::string(theme_name);
2349 edit_theme.
description = std::string(theme_description);
2350 edit_theme.
author = std::string(theme_author);
2353 std::string safe_name =
2354 edit_theme.
name.empty() ?
"custom_theme" : edit_theme.
name;
2358 if (!file_path.empty()) {
2360 if (file_path.find(
".theme") == std::string::npos) {
2361 file_path +=
".theme";
2370 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
2375 if (ImGui::IsItemHovered()) {
2376 ImGui::BeginTooltip();
2377 ImGui::Text(
"Save theme to a .theme file");
2378 ImGui::Text(
"Saved themes can be shared and loaded later");
2379 ImGui::EndTooltip();