1297 if (!p_open || !*p_open)
1300 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
1302 if (ImGui::Begin(absl::StrFormat(
"%s Theme Editor",
ICON_MD_PALETTE).c_str(),
1303 p_open, ImGuiWindowFlags_MenuBar)) {
1305 static float editor_animation_time = 0.0f;
1306 editor_animation_time += ImGui::GetIO().DeltaTime;
1308 ImDrawList* draw_list = ImGui::GetWindowDrawList();
1309 ImVec2 window_pos = ImGui::GetWindowPos();
1310 ImVec2 window_size = ImGui::GetWindowSize();
1314 std::vector<gui::Color> theme_colors = {
1315 current_theme.primary, current_theme.secondary, current_theme.accent,
1316 current_theme.success, current_theme.warning, current_theme.error};
1318 for (
size_t i = 0; i < theme_colors.size(); ++i) {
1319 float time_offset = i * 1.0f;
1320 float orbit_radius = 60.0f + i * 8.0f;
1321 float x = window_pos.x + window_size.x * 0.8f +
1322 cosf(editor_animation_time * 0.3f + time_offset) * orbit_radius;
1323 float y = window_pos.y + window_size.y * 0.3f +
1324 sinf(editor_animation_time * 0.3f + time_offset) * orbit_radius;
1327 0.15f + 0.1f * sinf(editor_animation_time * 1.5f + time_offset);
1328 ImU32 orb_color = ImGui::ColorConvertFloat4ToU32(
1329 ImVec4(theme_colors[i].red, theme_colors[i].green,
1330 theme_colors[i].blue, alpha));
1333 4.0f + sinf(editor_animation_time * 2.0f + time_offset) * 1.0f;
1334 draw_list->AddCircleFilled(ImVec2(x, y), radius, orb_color);
1338 if (ImGui::BeginMenuBar()) {
1339 if (ImGui::BeginMenu(
"File")) {
1340 if (ImGui::MenuItem(
1341 absl::StrFormat(
"%s New Theme",
ICON_MD_ADD).c_str())) {
1345 if (ImGui::MenuItem(
1349 if (!file_path.empty()) {
1354 if (ImGui::MenuItem(
1355 absl::StrFormat(
"%s Save Theme",
ICON_MD_SAVE).c_str())) {
1358 if (!current_file_path.empty()) {
1361 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1367 if (!file_path.empty()) {
1370 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1375 if (ImGui::MenuItem(
1380 if (!file_path.empty()) {
1383 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
1390 if (ImGui::BeginMenu(
"Presets")) {
1391 if (ImGui::MenuItem(
"YAZE Classic")) {
1396 if (!available_themes.empty()) {
1398 for (
const auto& theme_name : available_themes) {
1399 if (ImGui::MenuItem(theme_name.c_str())) {
1407 ImGui::EndMenuBar();
1411 static char theme_name[128];
1412 static char theme_description[256];
1413 static char theme_author[128];
1414 static bool live_preview =
true;
1415 static Theme original_theme;
1416 static bool theme_backup_made =
false;
1419 auto apply_live_preview = [&]() {
1421 if (!theme_backup_made) {
1423 theme_backup_made =
true;
1432 ImGui::Checkbox(
"Live Preview", &live_preview);
1434 ImGui::Text(
"| Changes apply immediately when enabled");
1437 static bool prev_live_preview = live_preview;
1438 if (prev_live_preview && !live_preview && theme_backup_made) {
1440 theme_backup_made =
false;
1442 prev_live_preview = live_preview;
1447 if (ImGui::BeginTable(
"ThemeMetadata", 2,
1448 ImGuiTableFlags_SizingStretchProp)) {
1449 ImGui::TableSetupColumn(
"Field", ImGuiTableColumnFlags_WidthFixed,
1451 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
1453 ImGui::TableNextRow();
1454 ImGui::TableNextColumn();
1455 ImGui::AlignTextToFramePadding();
1456 ImGui::Text(
"Name:");
1457 ImGui::TableNextColumn();
1458 if (ImGui::InputText(
"##theme_name", theme_name,
sizeof(theme_name))) {
1459 edit_theme.
name = std::string(theme_name);
1462 ImGui::TableNextRow();
1463 ImGui::TableNextColumn();
1464 ImGui::AlignTextToFramePadding();
1465 ImGui::Text(
"Description:");
1466 ImGui::TableNextColumn();
1467 if (ImGui::InputText(
"##theme_description", theme_description,
1468 sizeof(theme_description))) {
1469 edit_theme.
description = std::string(theme_description);
1472 ImGui::TableNextRow();
1473 ImGui::TableNextColumn();
1474 ImGui::AlignTextToFramePadding();
1475 ImGui::Text(
"Author:");
1476 ImGui::TableNextColumn();
1477 if (ImGui::InputText(
"##theme_author", theme_author,
1478 sizeof(theme_author))) {
1479 edit_theme.
author = std::string(theme_author);
1488 if (ImGui::BeginTabBar(
"ThemeEditorTabs", ImGuiTabBarFlags_None)) {
1490 static bool first_frame =
true;
1491 if (first_frame && live_preview) {
1492 apply_live_preview();
1493 first_frame =
false;
1497 if (ImGui::BeginTabItem(
1499 if (ImGui::BeginTable(
"PrimaryColorsTable", 3,
1500 ImGuiTableFlags_SizingStretchProp)) {
1501 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
1503 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1505 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
1507 ImGui::TableHeadersRow();
1510 ImGui::TableNextRow();
1511 ImGui::TableNextColumn();
1512 ImGui::AlignTextToFramePadding();
1513 ImGui::Text(
"Primary:");
1514 ImGui::TableNextColumn();
1516 if (ImGui::ColorEdit3(
"##primary", &primary.x)) {
1517 edit_theme.
primary = {primary.x, primary.y, primary.z, primary.w};
1518 apply_live_preview();
1520 ImGui::TableNextColumn();
1521 ImGui::Button(
"Primary Preview", ImVec2(-1, 30));
1524 ImGui::TableNextRow();
1525 ImGui::TableNextColumn();
1526 ImGui::AlignTextToFramePadding();
1527 ImGui::Text(
"Secondary:");
1528 ImGui::TableNextColumn();
1530 if (ImGui::ColorEdit3(
"##secondary", &secondary.x)) {
1531 edit_theme.
secondary = {secondary.x, secondary.y, secondary.z,
1533 apply_live_preview();
1535 ImGui::TableNextColumn();
1536 ImGui::PushStyleColor(ImGuiCol_Button, secondary);
1537 ImGui::Button(
"Secondary Preview", ImVec2(-1, 30));
1538 ImGui::PopStyleColor();
1541 ImGui::TableNextRow();
1542 ImGui::TableNextColumn();
1543 ImGui::AlignTextToFramePadding();
1544 ImGui::Text(
"Accent:");
1545 ImGui::TableNextColumn();
1547 if (ImGui::ColorEdit3(
"##accent", &accent.x)) {
1548 edit_theme.
accent = {accent.x, accent.y, accent.z, accent.w};
1549 apply_live_preview();
1551 ImGui::TableNextColumn();
1552 ImGui::PushStyleColor(ImGuiCol_Button, accent);
1553 ImGui::Button(
"Accent Preview", ImVec2(-1, 30));
1554 ImGui::PopStyleColor();
1557 ImGui::TableNextRow();
1558 ImGui::TableNextColumn();
1559 ImGui::AlignTextToFramePadding();
1560 ImGui::Text(
"Background:");
1561 ImGui::TableNextColumn();
1563 if (ImGui::ColorEdit4(
"##background", &background.x)) {
1564 edit_theme.
background = {background.x, background.y, background.z,
1566 apply_live_preview();
1568 ImGui::TableNextColumn();
1569 ImGui::Text(
"Background preview shown in window");
1573 ImGui::EndTabItem();
1577 if (ImGui::BeginTabItem(
1579 if (ImGui::BeginTable(
"TextColorsTable", 3,
1580 ImGuiTableFlags_SizingStretchProp)) {
1581 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
1583 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1585 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
1587 ImGui::TableHeadersRow();
1590 auto text_colors = std::vector<std::pair<const char*, Color*>>{
1600 for (
auto& [label, color_ptr] : text_colors) {
1601 ImGui::TableNextRow();
1602 ImGui::TableNextColumn();
1603 ImGui::AlignTextToFramePadding();
1604 ImGui::Text(
"%s:", label);
1606 ImGui::TableNextColumn();
1608 std::string
id = absl::StrFormat(
"##%s", label);
1609 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1610 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1611 apply_live_preview();
1614 ImGui::TableNextColumn();
1615 ImGui::PushStyleColor(ImGuiCol_Text, color_vec);
1616 ImGui::Text(
"Sample %s", label);
1617 ImGui::PopStyleColor();
1622 ImGui::EndTabItem();
1626 if (ImGui::BeginTabItem(
1628 if (ImGui::BeginTable(
"InteractiveColorsTable", 3,
1629 ImGuiTableFlags_SizingStretchProp)) {
1630 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1632 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1634 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
1636 ImGui::TableHeadersRow();
1639 auto interactive_colors =
1640 std::vector<std::tuple<const char*, Color*, ImGuiCol>>{
1641 {
"Button", &edit_theme.
button, ImGuiCol_Button},
1643 ImGuiCol_ButtonHovered},
1645 ImGuiCol_ButtonActive},
1646 {
"Frame Background", &edit_theme.
frame_bg, ImGuiCol_FrameBg},
1648 ImGuiCol_FrameBgHovered},
1650 ImGuiCol_FrameBgActive},
1651 {
"Check Mark", &edit_theme.
check_mark, ImGuiCol_CheckMark},
1652 {
"Slider Grab", &edit_theme.
slider_grab, ImGuiCol_SliderGrab},
1654 ImGuiCol_SliderGrabActive}};
1656 for (
auto& [label, color_ptr, imgui_col] : interactive_colors) {
1657 ImGui::TableNextRow();
1658 ImGui::TableNextColumn();
1659 ImGui::AlignTextToFramePadding();
1660 ImGui::Text(
"%s:", label);
1662 ImGui::TableNextColumn();
1664 std::string
id = absl::StrFormat(
"##%s", label);
1665 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1666 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1667 apply_live_preview();
1670 ImGui::TableNextColumn();
1671 ImGui::PushStyleColor(imgui_col, color_vec);
1672 ImGui::Button(absl::StrFormat(
"Preview %s", label).c_str(),
1674 ImGui::PopStyleColor();
1679 ImGui::EndTabItem();
1683 if (ImGui::BeginTabItem(
1685 ImGui::Text(
"Rounding and Border Settings:");
1687 if (ImGui::SliderFloat(
"Window Rounding", &edit_theme.
window_rounding,
1692 if (ImGui::SliderFloat(
"Frame Rounding", &edit_theme.
frame_rounding,
1697 if (ImGui::SliderFloat(
"Scrollbar Rounding",
1702 if (ImGui::SliderFloat(
"Tab Rounding", &edit_theme.
tab_rounding, 0.0f,
1707 if (ImGui::SliderFloat(
"Grab Rounding", &edit_theme.
grab_rounding, 0.0f,
1714 ImGui::Text(
"Border Sizes:");
1716 if (ImGui::SliderFloat(
"Window Border Size",
1721 if (ImGui::SliderFloat(
"Frame Border Size",
1728 ImGui::Text(
"Animation & Effects:");
1730 if (ImGui::Checkbox(
"Enable Animations",
1736 if (ImGui::SliderFloat(
"Animation Speed", &edit_theme.
animation_speed,
1738 apply_live_preview();
1741 if (ImGui::Checkbox(
"Enable Glow Effects",
1747 ImGui::EndTabItem();
1751 if (ImGui::BeginTabItem(
1753 if (ImGui::BeginTable(
"NavigationTable", 3,
1754 ImGuiTableFlags_SizingStretchProp)) {
1755 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1757 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1759 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
1761 ImGui::TableHeadersRow();
1764 auto window_colors =
1765 std::vector<std::tuple<const char*, Color*, const char*>>{
1766 {
"Window Background", &edit_theme.
window_bg,
1767 "Main window background"},
1768 {
"Child Background", &edit_theme.
child_bg,
1769 "Child window background"},
1770 {
"Popup Background", &edit_theme.
popup_bg,
1771 "Popup window background"},
1772 {
"Modal Background", &edit_theme.
modal_bg,
1773 "Modal window background"},
1775 "Menu bar background"}};
1777 for (
auto& [label, color_ptr, description] : window_colors) {
1778 ImGui::TableNextRow();
1779 ImGui::TableNextColumn();
1780 ImGui::AlignTextToFramePadding();
1781 ImGui::Text(
"%s:", label);
1783 ImGui::TableNextColumn();
1785 std::string
id = absl::StrFormat(
"##window_%s", label);
1786 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1787 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1788 apply_live_preview();
1791 ImGui::TableNextColumn();
1792 ImGui::TextWrapped(
"%s", description);
1801 if (ImGui::CollapsingHeader(
"Headers & Tabs",
1802 ImGuiTreeNodeFlags_DefaultOpen)) {
1803 if (ImGui::BeginTable(
"HeaderTabTable", 3,
1804 ImGuiTableFlags_SizingStretchProp)) {
1805 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1807 ImGui::TableSetupColumn(
"Picker",
1808 ImGuiTableColumnFlags_WidthStretch, 0.6f);
1809 ImGui::TableSetupColumn(
"Preview",
1810 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1811 ImGui::TableHeadersRow();
1813 auto header_tab_colors =
1814 std::vector<std::pair<const char*, Color*>>{
1815 {
"Header", &edit_theme.
header},
1818 {
"Tab", &edit_theme.
tab},
1825 {
"Title Background", &edit_theme.
title_bg},
1829 for (
auto& [label, color_ptr] : header_tab_colors) {
1830 ImGui::TableNextRow();
1831 ImGui::TableNextColumn();
1832 ImGui::AlignTextToFramePadding();
1833 ImGui::Text(
"%s:", label);
1835 ImGui::TableNextColumn();
1837 std::string
id = absl::StrFormat(
"##header_%s", label);
1838 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1839 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
1841 apply_live_preview();
1844 ImGui::TableNextColumn();
1845 ImGui::PushStyleColor(ImGuiCol_Button, color_vec);
1846 ImGui::Button(absl::StrFormat(
"Preview %s", label).c_str(),
1848 ImGui::PopStyleColor();
1856 if (ImGui::CollapsingHeader(
"Navigation & Special")) {
1857 if (ImGui::BeginTable(
"NavSpecialTable", 3,
1858 ImGuiTableFlags_SizingStretchProp)) {
1859 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1861 ImGui::TableSetupColumn(
"Picker",
1862 ImGuiTableColumnFlags_WidthStretch, 0.6f);
1863 ImGui::TableSetupColumn(
"Description",
1864 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1865 ImGui::TableHeadersRow();
1867 auto nav_special_colors =
1868 std::vector<std::tuple<const char*, Color*, const char*>>{
1870 "Navigation cursor color"},
1872 "Window selection highlight"},
1874 "Background dimming for navigation"},
1876 "Background dimming for modals"},
1878 "Drag and drop target highlight"},
1880 "Docking area preview"},
1882 "Empty docking space background"}};
1884 for (
auto& [label, color_ptr, description] : nav_special_colors) {
1885 ImGui::TableNextRow();
1886 ImGui::TableNextColumn();
1887 ImGui::AlignTextToFramePadding();
1888 ImGui::Text(
"%s:", label);
1890 ImGui::TableNextColumn();
1892 std::string
id = absl::StrFormat(
"##nav_%s", label);
1893 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1894 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
1896 apply_live_preview();
1899 ImGui::TableNextColumn();
1900 ImGui::TextWrapped(
"%s", description);
1907 ImGui::EndTabItem();
1911 if (ImGui::BeginTabItem(
1913 if (ImGui::BeginTable(
"TablesDataTable", 3,
1914 ImGuiTableFlags_SizingStretchProp)) {
1915 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1917 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
1919 ImGui::TableSetupColumn(
"Description",
1920 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1921 ImGui::TableHeadersRow();
1924 std::vector<std::tuple<const char*, Color*, const char*>>{
1926 "Table column headers"},
1928 "Outer table borders"},
1930 "Inner table borders"},
1932 "Normal table rows"},
1934 "Alternating table rows"},
1936 "Tree view connection lines"}};
1938 for (
auto& [label, color_ptr, description] : table_colors) {
1939 ImGui::TableNextRow();
1940 ImGui::TableNextColumn();
1941 ImGui::AlignTextToFramePadding();
1942 ImGui::Text(
"%s:", label);
1944 ImGui::TableNextColumn();
1946 std::string
id = absl::StrFormat(
"##table_%s", label);
1947 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
1948 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
1949 apply_live_preview();
1952 ImGui::TableNextColumn();
1953 ImGui::TextWrapped(
"%s", description);
1962 if (ImGui::CollapsingHeader(
"Plots & Graphs")) {
1963 if (ImGui::BeginTable(
"PlotsTable", 3,
1964 ImGuiTableFlags_SizingStretchProp)) {
1965 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
1967 ImGui::TableSetupColumn(
"Picker",
1968 ImGuiTableColumnFlags_WidthStretch, 0.6f);
1969 ImGui::TableSetupColumn(
"Description",
1970 ImGuiTableColumnFlags_WidthStretch, 0.4f);
1971 ImGui::TableHeadersRow();
1974 std::vector<std::tuple<const char*, Color*, const char*>>{
1975 {
"Plot Lines", &edit_theme.
plot_lines,
"Line plot color"},
1977 "Line plot hover color"},
1979 "Histogram fill color"},
1980 {
"Plot Histogram Hovered",
1982 "Histogram hover color"}};
1984 for (
auto& [label, color_ptr, description] : plot_colors) {
1985 ImGui::TableNextRow();
1986 ImGui::TableNextColumn();
1987 ImGui::AlignTextToFramePadding();
1988 ImGui::Text(
"%s:", label);
1990 ImGui::TableNextColumn();
1992 std::string
id = absl::StrFormat(
"##plot_%s", label);
1993 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
1994 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
1996 apply_live_preview();
1999 ImGui::TableNextColumn();
2000 ImGui::TextWrapped(
"%s", description);
2007 ImGui::EndTabItem();
2011 if (ImGui::BeginTabItem(
2013 if (ImGui::BeginTable(
"BordersControlsTable", 3,
2014 ImGuiTableFlags_SizingStretchProp)) {
2015 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2017 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
2019 ImGui::TableSetupColumn(
"Description",
2020 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2021 ImGui::TableHeadersRow();
2023 auto border_control_colors =
2024 std::vector<std::tuple<const char*, Color*, const char*>>{
2025 {
"Border", &edit_theme.
border,
"General border color"},
2027 "Border shadow/depth"},
2029 "Horizontal/vertical separators"},
2031 "Separator hover state"},
2033 "Separator active/dragged state"},
2035 "Scrollbar track background"},
2037 "Scrollbar handle"},
2039 "Scrollbar handle hover"},
2041 "Scrollbar handle active"},
2043 "Window resize grip"},
2045 "Resize grip hover"},
2047 "Resize grip active"}};
2049 for (
auto& [label, color_ptr, description] : border_control_colors) {
2050 ImGui::TableNextRow();
2051 ImGui::TableNextColumn();
2052 ImGui::AlignTextToFramePadding();
2053 ImGui::Text(
"%s:", label);
2055 ImGui::TableNextColumn();
2057 std::string
id = absl::StrFormat(
"##border_%s", label);
2058 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
2059 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
2060 apply_live_preview();
2063 ImGui::TableNextColumn();
2064 ImGui::TextWrapped(
"%s", description);
2070 ImGui::EndTabItem();
2074 if (ImGui::BeginTabItem(
2077 "Enhanced semantic colors and editor-specific customization");
2081 if (ImGui::CollapsingHeader(
"Enhanced Semantic Colors",
2082 ImGuiTreeNodeFlags_DefaultOpen)) {
2083 if (ImGui::BeginTable(
"EnhancedSemanticTable", 3,
2084 ImGuiTableFlags_SizingStretchProp)) {
2085 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
2087 ImGui::TableSetupColumn(
"Picker",
2088 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2089 ImGui::TableSetupColumn(
"Description",
2090 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2091 ImGui::TableHeadersRow();
2093 auto enhanced_colors =
2094 std::vector<std::tuple<const char*, Color*, const char*>>{
2096 "Code blocks background"},
2098 "Light success variant"},
2100 "Light warning variant"},
2102 "Light error variant"},
2104 "Light info variant"}};
2106 for (
auto& [label, color_ptr, description] : enhanced_colors) {
2107 ImGui::TableNextRow();
2108 ImGui::TableNextColumn();
2109 ImGui::AlignTextToFramePadding();
2110 ImGui::Text(
"%s:", label);
2112 ImGui::TableNextColumn();
2114 std::string
id = absl::StrFormat(
"##enhanced_%s", label);
2115 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
2116 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
2118 apply_live_preview();
2121 ImGui::TableNextColumn();
2122 ImGui::TextWrapped(
"%s", description);
2130 if (ImGui::CollapsingHeader(
"UI State Colors")) {
2131 if (ImGui::BeginTable(
"UIStateTable", 3,
2132 ImGuiTableFlags_SizingStretchProp)) {
2133 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
2135 ImGui::TableSetupColumn(
"Picker",
2136 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2137 ImGui::TableSetupColumn(
"Description",
2138 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2139 ImGui::TableHeadersRow();
2142 ImGui::TableNextRow();
2143 ImGui::TableNextColumn();
2144 ImGui::AlignTextToFramePadding();
2145 ImGui::Text(
"Active Selection:");
2146 ImGui::TableNextColumn();
2147 ImVec4 active_selection =
2149 if (ImGui::ColorEdit4(
"##active_selection", &active_selection.x)) {
2151 active_selection.x, active_selection.y, active_selection.z,
2152 active_selection.w};
2153 apply_live_preview();
2155 ImGui::TableNextColumn();
2156 ImGui::TextWrapped(
"Active/selected UI elements");
2158 ImGui::TableNextRow();
2159 ImGui::TableNextColumn();
2160 ImGui::AlignTextToFramePadding();
2161 ImGui::Text(
"Hover Highlight:");
2162 ImGui::TableNextColumn();
2163 ImVec4 hover_highlight =
2165 if (ImGui::ColorEdit4(
"##hover_highlight", &hover_highlight.x)) {
2167 hover_highlight.x, hover_highlight.y, hover_highlight.z,
2169 apply_live_preview();
2171 ImGui::TableNextColumn();
2172 ImGui::TextWrapped(
"General hover state highlighting");
2174 ImGui::TableNextRow();
2175 ImGui::TableNextColumn();
2176 ImGui::AlignTextToFramePadding();
2177 ImGui::Text(
"Focus Border:");
2178 ImGui::TableNextColumn();
2180 if (ImGui::ColorEdit3(
"##focus_border", &focus_border.x)) {
2181 edit_theme.
focus_border = {focus_border.x, focus_border.y,
2182 focus_border.z, focus_border.w};
2183 apply_live_preview();
2185 ImGui::TableNextColumn();
2186 ImGui::TextWrapped(
"Border for focused input elements");
2188 ImGui::TableNextRow();
2189 ImGui::TableNextColumn();
2190 ImGui::AlignTextToFramePadding();
2191 ImGui::Text(
"Disabled Overlay:");
2192 ImGui::TableNextColumn();
2193 ImVec4 disabled_overlay =
2195 if (ImGui::ColorEdit4(
"##disabled_overlay", &disabled_overlay.x)) {
2197 disabled_overlay.x, disabled_overlay.y, disabled_overlay.z,
2198 disabled_overlay.w};
2199 apply_live_preview();
2201 ImGui::TableNextColumn();
2203 "Semi-transparent overlay for disabled elements");
2210 if (ImGui::CollapsingHeader(
"Editor-Specific Colors")) {
2211 if (ImGui::BeginTable(
"EditorColorsTable", 3,
2212 ImGuiTableFlags_SizingStretchProp)) {
2213 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
2215 ImGui::TableSetupColumn(
"Picker",
2216 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2217 ImGui::TableSetupColumn(
"Description",
2218 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2219 ImGui::TableHeadersRow();
2221 auto editor_colors =
2222 std::vector<std::tuple<const char*, Color*, const char*, bool>>{
2224 "Main editor canvas background",
false},
2226 "Grid lines in map/graphics editors",
true},
2228 "Cursor color in editors",
false},
2230 "Selection highlight in editors",
true}};
2232 for (
auto& [label, color_ptr, description, use_alpha] :
2234 ImGui::TableNextRow();
2235 ImGui::TableNextColumn();
2236 ImGui::AlignTextToFramePadding();
2237 ImGui::Text(
"%s:", label);
2239 ImGui::TableNextColumn();
2241 std::string
id = absl::StrFormat(
"##editor_%s", label);
2242 if (use_alpha ? ImGui::ColorEdit4(
id.c_str(), &color_vec.x)
2243 : ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
2244 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
2246 apply_live_preview();
2249 ImGui::TableNextColumn();
2250 ImGui::TextWrapped(
"%s", description);
2257 ImGui::EndTabItem();
2265 if (ImGui::Button(
"Preview Theme")) {
2270 if (ImGui::Button(
"Reset to Current")) {
2276 theme_name[name_len] =
'\0';
2279 sizeof(theme_description) - 1);
2282 theme_description[desc_len] =
'\0';
2287 theme_author[author_len] =
'\0';
2290 if (theme_backup_made) {
2291 theme_backup_made =
false;
2298 if (ImGui::Button(
"Save Theme")) {
2299 edit_theme.
name = std::string(theme_name);
2300 edit_theme.
description = std::string(theme_description);
2301 edit_theme.
author = std::string(theme_author);
2308 theme_backup_made =
false;
2315 bool can_save_over = !current_file_path.empty();
2317 if (!can_save_over) {
2318 ImGui::BeginDisabled();
2321 if (ImGui::Button(
"Save Over Current")) {
2322 edit_theme.
name = std::string(theme_name);
2323 edit_theme.
description = std::string(theme_description);
2324 edit_theme.
author = std::string(theme_author);
2334 LOG_ERROR(
"Theme Manager",
"Failed to save over current theme");
2338 if (!can_save_over) {
2339 ImGui::EndDisabled();
2342 if (ImGui::IsItemHovered() && can_save_over) {
2343 ImGui::BeginTooltip();
2344 ImGui::Text(
"Save over current theme file:");
2345 ImGui::Text(
"%s", current_file_path.c_str());
2346 ImGui::EndTooltip();
2347 }
else if (ImGui::IsItemHovered()) {
2348 ImGui::BeginTooltip();
2349 ImGui::Text(
"No current theme file to overwrite");
2350 ImGui::Text(
"Use 'Save to File...' to create a new theme file");
2351 ImGui::EndTooltip();
2355 if (ImGui::Button(
"Save to File...")) {
2356 edit_theme.
name = std::string(theme_name);
2357 edit_theme.
description = std::string(theme_description);
2358 edit_theme.
author = std::string(theme_author);
2361 std::string safe_name =
2362 edit_theme.
name.empty() ?
"custom_theme" : edit_theme.
name;
2366 if (!file_path.empty()) {
2368 if (file_path.find(
".theme") == std::string::npos) {
2369 file_path +=
".theme";
2378 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
2383 if (ImGui::IsItemHovered()) {
2384 ImGui::BeginTooltip();
2385 ImGui::Text(
"Save theme to a .theme file");
2386 ImGui::Text(
"Saved themes can be shared and loaded later");
2387 ImGui::EndTooltip();