2136 if (!p_open || !*p_open)
2139 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
2141 if (ImGui::Begin(absl::StrFormat(
"%s Theme Editor",
ICON_MD_PALETTE).c_str(),
2142 p_open, ImGuiWindowFlags_MenuBar)) {
2144 static float editor_animation_time = 0.0f;
2145 editor_animation_time += ImGui::GetIO().DeltaTime;
2147 ImDrawList* draw_list = ImGui::GetWindowDrawList();
2148 ImVec2 window_pos = ImGui::GetWindowPos();
2149 ImVec2 window_size = ImGui::GetWindowSize();
2153 std::vector<gui::Color> theme_colors = {
2154 current_theme.primary, current_theme.secondary, current_theme.accent,
2155 current_theme.success, current_theme.warning, current_theme.error};
2157 for (
size_t i = 0; i < theme_colors.size(); ++i) {
2158 float time_offset = i * 1.0f;
2159 float orbit_radius = 60.0f + i * 8.0f;
2160 float x = window_pos.x + window_size.x * 0.8f +
2161 cosf(editor_animation_time * 0.3f + time_offset) * orbit_radius;
2162 float y = window_pos.y + window_size.y * 0.3f +
2163 sinf(editor_animation_time * 0.3f + time_offset) * orbit_radius;
2166 0.15f + 0.1f * sinf(editor_animation_time * 1.5f + time_offset);
2167 ImU32 orb_color = ImGui::ColorConvertFloat4ToU32(
2168 ImVec4(theme_colors[i].red, theme_colors[i].green,
2169 theme_colors[i].blue, alpha));
2172 4.0f + sinf(editor_animation_time * 2.0f + time_offset) * 1.0f;
2173 draw_list->AddCircleFilled(ImVec2(x, y), radius, orb_color);
2177 if (ImGui::BeginMenuBar()) {
2178 if (ImGui::BeginMenu(
"File")) {
2179 if (ImGui::MenuItem(
2180 absl::StrFormat(
"%s New Theme",
ICON_MD_ADD).c_str())) {
2184 if (ImGui::MenuItem(
2188 if (!file_path.empty()) {
2193 if (ImGui::MenuItem(
2194 absl::StrFormat(
"%s Save Theme",
ICON_MD_SAVE).c_str())) {
2197 if (!current_file_path.empty()) {
2200 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
2206 if (!file_path.empty()) {
2209 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
2214 if (ImGui::MenuItem(
2219 if (!file_path.empty()) {
2222 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
2227 if (ImGui::MenuItem(
2236 for (
char& c : safe_name) {
2237 if (c ==
' ' || c ==
'/' || c ==
'\\' || c ==
':' || c ==
'*' ||
2238 c ==
'?' || c ==
'"' || c ==
'<' || c ==
'>' || c ==
'|') {
2242 std::string file_path = user_themes_dir + safe_name +
".theme";
2246 LOG_INFO(
"Theme Manager",
"Exported theme to: %s",
2249 LOG_ERROR(
"Theme Manager",
"Failed to export theme to user themes");
2255 if (ImGui::BeginMenu(
"Presets")) {
2256 if (ImGui::MenuItem(
"YAZE Classic")) {
2261 if (!available_themes.empty()) {
2263 for (
const auto& theme_name : available_themes) {
2264 if (ImGui::MenuItem(theme_name.c_str())) {
2272 ImGui::EndMenuBar();
2276 static char theme_name[128];
2277 static char theme_description[256];
2278 static char theme_author[128];
2279 static bool live_preview =
true;
2280 static Theme original_theme;
2281 static bool theme_backup_made =
false;
2284 auto apply_live_preview = [&]() {
2286 if (!theme_backup_made) {
2288 theme_backup_made =
true;
2297 ImGui::Checkbox(
"Live Preview", &live_preview);
2299 ImGui::Text(
"| Changes apply immediately when enabled");
2302 static bool prev_live_preview = live_preview;
2303 if (prev_live_preview && !live_preview && theme_backup_made) {
2305 theme_backup_made =
false;
2307 prev_live_preview = live_preview;
2312 if (ImGui::BeginTable(
"ThemeMetadata", 2,
2313 ImGuiTableFlags_SizingStretchProp)) {
2314 ImGui::TableSetupColumn(
"Field", ImGuiTableColumnFlags_WidthFixed,
2316 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
2318 ImGui::TableNextRow();
2319 ImGui::TableNextColumn();
2320 ImGui::AlignTextToFramePadding();
2321 ImGui::Text(
"Name:");
2322 ImGui::TableNextColumn();
2323 if (ImGui::InputText(
"##theme_name", theme_name,
sizeof(theme_name))) {
2324 edit_theme.
name = std::string(theme_name);
2327 ImGui::TableNextRow();
2328 ImGui::TableNextColumn();
2329 ImGui::AlignTextToFramePadding();
2330 ImGui::Text(
"Description:");
2331 ImGui::TableNextColumn();
2332 if (ImGui::InputText(
"##theme_description", theme_description,
2333 sizeof(theme_description))) {
2334 edit_theme.
description = std::string(theme_description);
2337 ImGui::TableNextRow();
2338 ImGui::TableNextColumn();
2339 ImGui::AlignTextToFramePadding();
2340 ImGui::Text(
"Author:");
2341 ImGui::TableNextColumn();
2342 if (ImGui::InputText(
"##theme_author", theme_author,
2343 sizeof(theme_author))) {
2344 edit_theme.
author = std::string(theme_author);
2353 if (ImGui::BeginTabBar(
"ThemeEditorTabs", ImGuiTabBarFlags_None)) {
2355 static bool first_frame =
true;
2356 if (first_frame && live_preview) {
2357 apply_live_preview();
2358 first_frame =
false;
2362 if (ImGui::BeginTabItem(
2366 ImGui::PushStyleColor(ImGuiCol_ChildBg,
2367 ImVec4(0.1f, 0.1f, 0.12f, 0.5f));
2368 ImGui::BeginChild(
"AccentGenerator", ImVec2(0, 120),
true);
2370 ImGui::TextColored(ImVec4(0.7f, 0.8f, 1.0f, 1.0f),
2371 "%s Generate Theme from Accent Color",
2375 static Color accent_picker_color = {0.4f, 0.6f, 0.9f, 1.0f};
2376 static bool dark_mode_generate =
true;
2378 ImGui::Text(
"Accent Color:");
2381 if (ImGui::ColorEdit3(
"##AccentPicker", &accent_vec.x,
2382 ImGuiColorEditFlags_NoInputs)) {
2383 accent_picker_color = {accent_vec.x, accent_vec.y, accent_vec.z,
2388 ImGui::Checkbox(
"Dark Mode", &dark_mode_generate);
2391 if (ImGui::Button(absl::StrFormat(
"%s Generate",
ICON_MD_BOLT).c_str(),
2396 edit_theme = generated;
2397 apply_live_preview();
2401 ImGui::Text(
"Preview: ");
2405 Theme preview_theme =
2412 ImGui::ColorButton(
"##prev_primary", prev_primary, 0, ImVec2(24, 24));
2413 ImGui::SameLine(0, 2);
2414 ImGui::ColorButton(
"##prev_secondary", prev_secondary, 0,
2416 ImGui::SameLine(0, 2);
2417 ImGui::ColorButton(
"##prev_bg", prev_bg, 0, ImVec2(24, 24));
2418 ImGui::SameLine(0, 2);
2419 ImGui::ColorButton(
"##prev_surface", prev_surface, 0, ImVec2(24, 24));
2422 ImGui::PopStyleColor();
2426 if (ImGui::BeginTable(
"PrimaryColorsTable", 3,
2427 ImGuiTableFlags_SizingStretchProp)) {
2428 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
2430 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
2432 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
2434 ImGui::TableHeadersRow();
2437 ImGui::TableNextRow();
2438 ImGui::TableNextColumn();
2439 ImGui::AlignTextToFramePadding();
2440 ImGui::Text(
"Primary:");
2441 ImGui::TableNextColumn();
2443 if (ImGui::ColorEdit3(
"##primary", &primary.x)) {
2444 edit_theme.
primary = {primary.x, primary.y, primary.z, primary.w};
2445 apply_live_preview();
2447 ImGui::TableNextColumn();
2448 ImGui::Button(
"Primary Preview", ImVec2(-1, 30));
2451 ImGui::TableNextRow();
2452 ImGui::TableNextColumn();
2453 ImGui::AlignTextToFramePadding();
2454 ImGui::Text(
"Secondary:");
2455 ImGui::TableNextColumn();
2457 if (ImGui::ColorEdit3(
"##secondary", &secondary.x)) {
2458 edit_theme.
secondary = {secondary.x, secondary.y, secondary.z,
2460 apply_live_preview();
2462 ImGui::TableNextColumn();
2463 ImGui::PushStyleColor(ImGuiCol_Button, secondary);
2464 ImGui::Button(
"Secondary Preview", ImVec2(-1, 30));
2465 ImGui::PopStyleColor();
2468 ImGui::TableNextRow();
2469 ImGui::TableNextColumn();
2470 ImGui::AlignTextToFramePadding();
2471 ImGui::Text(
"Accent:");
2472 ImGui::TableNextColumn();
2474 if (ImGui::ColorEdit3(
"##accent", &accent.x)) {
2475 edit_theme.
accent = {accent.x, accent.y, accent.z, accent.w};
2476 apply_live_preview();
2478 ImGui::TableNextColumn();
2479 ImGui::PushStyleColor(ImGuiCol_Button, accent);
2480 ImGui::Button(
"Accent Preview", ImVec2(-1, 30));
2481 ImGui::PopStyleColor();
2484 ImGui::TableNextRow();
2485 ImGui::TableNextColumn();
2486 ImGui::AlignTextToFramePadding();
2487 ImGui::Text(
"Background:");
2488 ImGui::TableNextColumn();
2490 if (ImGui::ColorEdit4(
"##background", &background.x)) {
2491 edit_theme.
background = {background.x, background.y, background.z,
2493 apply_live_preview();
2495 ImGui::TableNextColumn();
2496 ImGui::Text(
"Background preview shown in window");
2500 ImGui::EndTabItem();
2504 if (ImGui::BeginTabItem(
2506 if (ImGui::BeginTable(
"TextColorsTable", 3,
2507 ImGuiTableFlags_SizingStretchProp)) {
2508 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
2510 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
2512 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
2514 ImGui::TableHeadersRow();
2517 auto text_colors = std::vector<std::pair<const char*, Color*>>{
2527 for (
auto& [label, color_ptr] : text_colors) {
2528 ImGui::TableNextRow();
2529 ImGui::TableNextColumn();
2530 ImGui::AlignTextToFramePadding();
2531 ImGui::Text(
"%s:", label);
2533 ImGui::TableNextColumn();
2535 std::string
id = absl::StrFormat(
"##%s", label);
2536 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
2537 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
2538 apply_live_preview();
2541 ImGui::TableNextColumn();
2542 ImGui::PushStyleColor(ImGuiCol_Text, color_vec);
2543 ImGui::Text(
"Sample %s", label);
2544 ImGui::PopStyleColor();
2549 ImGui::EndTabItem();
2553 if (ImGui::BeginTabItem(
2555 if (ImGui::BeginTable(
"InteractiveColorsTable", 3,
2556 ImGuiTableFlags_SizingStretchProp)) {
2557 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2559 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
2561 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
2563 ImGui::TableHeadersRow();
2566 auto interactive_colors =
2567 std::vector<std::tuple<const char*, Color*, ImGuiCol>>{
2568 {
"Button", &edit_theme.
button, ImGuiCol_Button},
2570 ImGuiCol_ButtonHovered},
2572 ImGuiCol_ButtonActive},
2573 {
"Frame Background", &edit_theme.
frame_bg, ImGuiCol_FrameBg},
2575 ImGuiCol_FrameBgHovered},
2577 ImGuiCol_FrameBgActive},
2578 {
"Check Mark", &edit_theme.
check_mark, ImGuiCol_CheckMark},
2579 {
"Slider Grab", &edit_theme.
slider_grab, ImGuiCol_SliderGrab},
2581 ImGuiCol_SliderGrabActive}};
2583 for (
auto& [label, color_ptr, imgui_col] : interactive_colors) {
2584 ImGui::TableNextRow();
2585 ImGui::TableNextColumn();
2586 ImGui::AlignTextToFramePadding();
2587 ImGui::Text(
"%s:", label);
2589 ImGui::TableNextColumn();
2591 std::string
id = absl::StrFormat(
"##%s", label);
2592 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
2593 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
2594 apply_live_preview();
2597 ImGui::TableNextColumn();
2598 ImGui::PushStyleColor(imgui_col, color_vec);
2599 ImGui::Button(absl::StrFormat(
"Preview %s", label).c_str(),
2601 ImGui::PopStyleColor();
2606 ImGui::EndTabItem();
2610 if (ImGui::BeginTabItem(
2612 ImGui::Text(
"Rounding and Border Settings:");
2614 if (ImGui::SliderFloat(
"Window Rounding", &edit_theme.
window_rounding,
2619 if (ImGui::SliderFloat(
"Frame Rounding", &edit_theme.
frame_rounding,
2624 if (ImGui::SliderFloat(
"Scrollbar Rounding",
2629 if (ImGui::SliderFloat(
"Tab Rounding", &edit_theme.
tab_rounding, 0.0f,
2634 if (ImGui::SliderFloat(
"Grab Rounding", &edit_theme.
grab_rounding, 0.0f,
2641 ImGui::Text(
"Border Sizes:");
2643 if (ImGui::SliderFloat(
"Window Border Size",
2648 if (ImGui::SliderFloat(
"Frame Border Size",
2655 ImGui::Text(
"Animation & Effects:");
2657 if (ImGui::Checkbox(
"Enable Animations",
2663 if (ImGui::SliderFloat(
"Animation Speed", &edit_theme.
animation_speed,
2665 apply_live_preview();
2668 if (ImGui::Checkbox(
"Enable Glow Effects",
2674 ImGui::EndTabItem();
2678 if (ImGui::BeginTabItem(
2680 if (ImGui::BeginTable(
"NavigationTable", 3,
2681 ImGuiTableFlags_SizingStretchProp)) {
2682 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2684 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
2686 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
2688 ImGui::TableHeadersRow();
2691 auto window_colors =
2692 std::vector<std::tuple<const char*, Color*, const char*>>{
2693 {
"Window Background", &edit_theme.
window_bg,
2694 "Main window background"},
2695 {
"Child Background", &edit_theme.
child_bg,
2696 "Child window background"},
2697 {
"Popup Background", &edit_theme.
popup_bg,
2698 "Popup window background"},
2699 {
"Modal Background", &edit_theme.
modal_bg,
2700 "Modal window background"},
2702 "Menu bar background"}};
2704 for (
auto& [label, color_ptr, description] : window_colors) {
2705 ImGui::TableNextRow();
2706 ImGui::TableNextColumn();
2707 ImGui::AlignTextToFramePadding();
2708 ImGui::Text(
"%s:", label);
2710 ImGui::TableNextColumn();
2712 std::string
id = absl::StrFormat(
"##window_%s", label);
2713 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
2714 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
2715 apply_live_preview();
2718 ImGui::TableNextColumn();
2719 ImGui::TextWrapped(
"%s", description);
2728 if (ImGui::CollapsingHeader(
"Headers & Tabs",
2729 ImGuiTreeNodeFlags_DefaultOpen)) {
2730 if (ImGui::BeginTable(
"HeaderTabTable", 3,
2731 ImGuiTableFlags_SizingStretchProp)) {
2732 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2734 ImGui::TableSetupColumn(
"Picker",
2735 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2736 ImGui::TableSetupColumn(
"Preview",
2737 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2738 ImGui::TableHeadersRow();
2740 auto header_tab_colors =
2741 std::vector<std::pair<const char*, Color*>>{
2742 {
"Header", &edit_theme.
header},
2745 {
"Tab", &edit_theme.
tab},
2752 {
"Title Background", &edit_theme.
title_bg},
2756 for (
auto& [label, color_ptr] : header_tab_colors) {
2757 ImGui::TableNextRow();
2758 ImGui::TableNextColumn();
2759 ImGui::AlignTextToFramePadding();
2760 ImGui::Text(
"%s:", label);
2762 ImGui::TableNextColumn();
2764 std::string
id = absl::StrFormat(
"##header_%s", label);
2765 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
2766 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
2768 apply_live_preview();
2771 ImGui::TableNextColumn();
2772 ImGui::PushStyleColor(ImGuiCol_Button, color_vec);
2773 ImGui::Button(absl::StrFormat(
"Preview %s", label).c_str(),
2775 ImGui::PopStyleColor();
2783 if (ImGui::CollapsingHeader(
"Navigation & Special")) {
2784 if (ImGui::BeginTable(
"NavSpecialTable", 3,
2785 ImGuiTableFlags_SizingStretchProp)) {
2786 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2788 ImGui::TableSetupColumn(
"Picker",
2789 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2790 ImGui::TableSetupColumn(
"Description",
2791 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2792 ImGui::TableHeadersRow();
2794 auto nav_special_colors =
2795 std::vector<std::tuple<const char*, Color*, const char*>>{
2797 "Navigation cursor color"},
2799 "Window selection highlight"},
2801 "Background dimming for navigation"},
2803 "Background dimming for modals"},
2805 "Drag and drop target highlight"},
2807 "Docking area preview"},
2809 "Empty docking space background"}};
2811 for (
auto& [label, color_ptr, description] : nav_special_colors) {
2812 ImGui::TableNextRow();
2813 ImGui::TableNextColumn();
2814 ImGui::AlignTextToFramePadding();
2815 ImGui::Text(
"%s:", label);
2817 ImGui::TableNextColumn();
2819 std::string
id = absl::StrFormat(
"##nav_%s", label);
2820 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
2821 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
2823 apply_live_preview();
2826 ImGui::TableNextColumn();
2827 ImGui::TextWrapped(
"%s", description);
2834 ImGui::EndTabItem();
2838 if (ImGui::BeginTabItem(
2840 if (ImGui::BeginTable(
"TablesDataTable", 3,
2841 ImGuiTableFlags_SizingStretchProp)) {
2842 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2844 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
2846 ImGui::TableSetupColumn(
"Description",
2847 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2848 ImGui::TableHeadersRow();
2851 std::vector<std::tuple<const char*, Color*, const char*>>{
2853 "Table column headers"},
2855 "Outer table borders"},
2857 "Inner table borders"},
2859 "Normal table rows"},
2861 "Alternating table rows"},
2863 "Tree view connection lines"}};
2865 for (
auto& [label, color_ptr, description] : table_colors) {
2866 ImGui::TableNextRow();
2867 ImGui::TableNextColumn();
2868 ImGui::AlignTextToFramePadding();
2869 ImGui::Text(
"%s:", label);
2871 ImGui::TableNextColumn();
2873 std::string
id = absl::StrFormat(
"##table_%s", label);
2874 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
2875 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
2876 apply_live_preview();
2879 ImGui::TableNextColumn();
2880 ImGui::TextWrapped(
"%s", description);
2889 if (ImGui::CollapsingHeader(
"Plots & Graphs")) {
2890 if (ImGui::BeginTable(
"PlotsTable", 3,
2891 ImGuiTableFlags_SizingStretchProp)) {
2892 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2894 ImGui::TableSetupColumn(
"Picker",
2895 ImGuiTableColumnFlags_WidthStretch, 0.6f);
2896 ImGui::TableSetupColumn(
"Description",
2897 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2898 ImGui::TableHeadersRow();
2901 std::vector<std::tuple<const char*, Color*, const char*>>{
2902 {
"Plot Lines", &edit_theme.
plot_lines,
"Line plot color"},
2904 "Line plot hover color"},
2906 "Histogram fill color"},
2907 {
"Plot Histogram Hovered",
2909 "Histogram hover color"}};
2911 for (
auto& [label, color_ptr, description] : plot_colors) {
2912 ImGui::TableNextRow();
2913 ImGui::TableNextColumn();
2914 ImGui::AlignTextToFramePadding();
2915 ImGui::Text(
"%s:", label);
2917 ImGui::TableNextColumn();
2919 std::string
id = absl::StrFormat(
"##plot_%s", label);
2920 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
2921 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
2923 apply_live_preview();
2926 ImGui::TableNextColumn();
2927 ImGui::TextWrapped(
"%s", description);
2934 ImGui::EndTabItem();
2938 if (ImGui::BeginTabItem(
2940 if (ImGui::BeginTable(
"BordersControlsTable", 3,
2941 ImGuiTableFlags_SizingStretchProp)) {
2942 ImGui::TableSetupColumn(
"Element", ImGuiTableColumnFlags_WidthFixed,
2944 ImGui::TableSetupColumn(
"Picker", ImGuiTableColumnFlags_WidthStretch,
2946 ImGui::TableSetupColumn(
"Description",
2947 ImGuiTableColumnFlags_WidthStretch, 0.4f);
2948 ImGui::TableHeadersRow();
2950 auto border_control_colors =
2951 std::vector<std::tuple<const char*, Color*, const char*>>{
2952 {
"Border", &edit_theme.
border,
"General border color"},
2954 "Border shadow/depth"},
2956 "Horizontal/vertical separators"},
2958 "Separator hover state"},
2960 "Separator active/dragged state"},
2962 "Scrollbar track background"},
2964 "Scrollbar handle"},
2966 "Scrollbar handle hover"},
2968 "Scrollbar handle active"},
2970 "Window resize grip"},
2972 "Resize grip hover"},
2974 "Resize grip active"}};
2976 for (
auto& [label, color_ptr, description] : border_control_colors) {
2977 ImGui::TableNextRow();
2978 ImGui::TableNextColumn();
2979 ImGui::AlignTextToFramePadding();
2980 ImGui::Text(
"%s:", label);
2982 ImGui::TableNextColumn();
2984 std::string
id = absl::StrFormat(
"##border_%s", label);
2985 if (ImGui::ColorEdit4(
id.c_str(), &color_vec.x)) {
2986 *color_ptr = {color_vec.x, color_vec.y, color_vec.z, color_vec.w};
2987 apply_live_preview();
2990 ImGui::TableNextColumn();
2991 ImGui::TextWrapped(
"%s", description);
2997 ImGui::EndTabItem();
3001 if (ImGui::BeginTabItem(
3004 "Enhanced semantic colors and editor-specific customization");
3008 if (ImGui::CollapsingHeader(
"Enhanced Semantic Colors",
3009 ImGuiTreeNodeFlags_DefaultOpen)) {
3010 if (ImGui::BeginTable(
"EnhancedSemanticTable", 3,
3011 ImGuiTableFlags_SizingStretchProp)) {
3012 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
3014 ImGui::TableSetupColumn(
"Picker",
3015 ImGuiTableColumnFlags_WidthStretch, 0.6f);
3016 ImGui::TableSetupColumn(
"Description",
3017 ImGuiTableColumnFlags_WidthStretch, 0.4f);
3018 ImGui::TableHeadersRow();
3020 auto enhanced_colors =
3021 std::vector<std::tuple<const char*, Color*, const char*>>{
3023 "Code blocks background"},
3025 "Light success variant"},
3027 "Light warning variant"},
3029 "Light error variant"},
3031 "Light info variant"}};
3033 for (
auto& [label, color_ptr, description] : enhanced_colors) {
3034 ImGui::TableNextRow();
3035 ImGui::TableNextColumn();
3036 ImGui::AlignTextToFramePadding();
3037 ImGui::Text(
"%s:", label);
3039 ImGui::TableNextColumn();
3041 std::string
id = absl::StrFormat(
"##enhanced_%s", label);
3042 if (ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
3043 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
3045 apply_live_preview();
3048 ImGui::TableNextColumn();
3049 ImGui::TextWrapped(
"%s", description);
3057 if (ImGui::CollapsingHeader(
"UI State Colors")) {
3058 if (ImGui::BeginTable(
"UIStateTable", 3,
3059 ImGuiTableFlags_SizingStretchProp)) {
3060 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
3062 ImGui::TableSetupColumn(
"Picker",
3063 ImGuiTableColumnFlags_WidthStretch, 0.6f);
3064 ImGui::TableSetupColumn(
"Description",
3065 ImGuiTableColumnFlags_WidthStretch, 0.4f);
3066 ImGui::TableHeadersRow();
3069 ImGui::TableNextRow();
3070 ImGui::TableNextColumn();
3071 ImGui::AlignTextToFramePadding();
3072 ImGui::Text(
"Active Selection:");
3073 ImGui::TableNextColumn();
3074 ImVec4 active_selection =
3076 if (ImGui::ColorEdit4(
"##active_selection", &active_selection.x)) {
3078 active_selection.x, active_selection.y, active_selection.z,
3079 active_selection.w};
3080 apply_live_preview();
3082 ImGui::TableNextColumn();
3083 ImGui::TextWrapped(
"Active/selected UI elements");
3085 ImGui::TableNextRow();
3086 ImGui::TableNextColumn();
3087 ImGui::AlignTextToFramePadding();
3088 ImGui::Text(
"Hover Highlight:");
3089 ImGui::TableNextColumn();
3090 ImVec4 hover_highlight =
3092 if (ImGui::ColorEdit4(
"##hover_highlight", &hover_highlight.x)) {
3094 hover_highlight.x, hover_highlight.y, hover_highlight.z,
3096 apply_live_preview();
3098 ImGui::TableNextColumn();
3099 ImGui::TextWrapped(
"General hover state highlighting");
3101 ImGui::TableNextRow();
3102 ImGui::TableNextColumn();
3103 ImGui::AlignTextToFramePadding();
3104 ImGui::Text(
"Focus Border:");
3105 ImGui::TableNextColumn();
3107 if (ImGui::ColorEdit3(
"##focus_border", &focus_border.x)) {
3108 edit_theme.
focus_border = {focus_border.x, focus_border.y,
3109 focus_border.z, focus_border.w};
3110 apply_live_preview();
3112 ImGui::TableNextColumn();
3113 ImGui::TextWrapped(
"Border for focused input elements");
3115 ImGui::TableNextRow();
3116 ImGui::TableNextColumn();
3117 ImGui::AlignTextToFramePadding();
3118 ImGui::Text(
"Disabled Overlay:");
3119 ImGui::TableNextColumn();
3120 ImVec4 disabled_overlay =
3122 if (ImGui::ColorEdit4(
"##disabled_overlay", &disabled_overlay.x)) {
3124 disabled_overlay.x, disabled_overlay.y, disabled_overlay.z,
3125 disabled_overlay.w};
3126 apply_live_preview();
3128 ImGui::TableNextColumn();
3130 "Semi-transparent overlay for disabled elements");
3137 if (ImGui::CollapsingHeader(
"Editor-Specific Colors")) {
3138 if (ImGui::BeginTable(
"EditorColorsTable", 3,
3139 ImGuiTableFlags_SizingStretchProp)) {
3140 ImGui::TableSetupColumn(
"Color", ImGuiTableColumnFlags_WidthFixed,
3142 ImGui::TableSetupColumn(
"Picker",
3143 ImGuiTableColumnFlags_WidthStretch, 0.6f);
3144 ImGui::TableSetupColumn(
"Description",
3145 ImGuiTableColumnFlags_WidthStretch, 0.4f);
3146 ImGui::TableHeadersRow();
3148 auto editor_colors =
3149 std::vector<std::tuple<const char*, Color*, const char*, bool>>{
3151 "Main editor canvas background",
false},
3153 "Grid lines in map/graphics editors",
true},
3155 "Cursor color in editors",
false},
3157 "Selection highlight in editors",
true}};
3159 for (
auto& [label, color_ptr, description, use_alpha] :
3161 ImGui::TableNextRow();
3162 ImGui::TableNextColumn();
3163 ImGui::AlignTextToFramePadding();
3164 ImGui::Text(
"%s:", label);
3166 ImGui::TableNextColumn();
3168 std::string
id = absl::StrFormat(
"##editor_%s", label);
3169 if (use_alpha ? ImGui::ColorEdit4(
id.c_str(), &color_vec.x)
3170 : ImGui::ColorEdit3(
id.c_str(), &color_vec.x)) {
3171 *color_ptr = {color_vec.x, color_vec.y, color_vec.z,
3173 apply_live_preview();
3176 ImGui::TableNextColumn();
3177 ImGui::TextWrapped(
"%s", description);
3184 ImGui::EndTabItem();
3188 if (ImGui::BeginTabItem(
3190 ImGui::Text(
"Control UI density, spacing, and typography scaling");
3194 ImGui::TextColored(ImVec4(0.7f, 0.8f, 1.0f, 1.0f),
"%s Quick Presets",
3199 int current_preset =
static_cast<int>(edit_theme.
density_preset);
3201 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20, 12));
3202 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(12, 0));
3205 bool is_compact = (current_preset == 0);
3207 ImGui::PushStyleColor(
3216 apply_live_preview();
3219 ImGui::PopStyleColor();
3221 if (ImGui::IsItemHovered()) {
3223 "Dense UI with smaller widgets and tighter spacing\n"
3224 "Best for: Information-dense workflows");
3230 bool is_normal = (current_preset == 1);
3232 ImGui::PushStyleColor(
3237 if (ImGui::Button(absl::StrFormat(
"%s Normal",
ICON_MD_CHECK).c_str(),
3240 apply_live_preview();
3243 ImGui::PopStyleColor();
3245 if (ImGui::IsItemHovered()) {
3247 "Balanced spacing and widget sizes\n"
3248 "Best for: General use");
3254 bool is_comfortable = (current_preset == 2);
3255 if (is_comfortable) {
3256 ImGui::PushStyleColor(
3265 apply_live_preview();
3267 if (is_comfortable) {
3268 ImGui::PopStyleColor();
3270 if (ImGui::IsItemHovered()) {
3272 "Spacious layout with larger click targets\n"
3273 "Best for: Touch screens, accessibility");
3276 ImGui::PopStyleVar(2);
3283 if (ImGui::CollapsingHeader(
"Advanced Density Controls")) {
3286 ImGui::Text(
"Fine-tune individual spacing multipliers:");
3290 if (ImGui::SliderFloat(
"Compact Factor", &edit_theme.
compact_factor,
3291 0.5f, 1.5f,
"%.2f")) {
3292 apply_live_preview();
3294 if (ImGui::IsItemHovered()) {
3296 "Global density multiplier (0.5 = very compact, "
3297 "1.5 = very spacious)");
3303 if (ImGui::SliderFloat(
"Widget Height",
3306 apply_live_preview();
3311 0.5f, 1.5f,
"%.2f")) {
3312 apply_live_preview();
3316 if (ImGui::SliderFloat(
"Toolbar Height",
3319 apply_live_preview();
3323 if (ImGui::SliderFloat(
"Panel Padding",
3326 apply_live_preview();
3330 if (ImGui::SliderFloat(
"Button Padding",
3333 apply_live_preview();
3337 if (ImGui::SliderFloat(
"Table Row Height",
3340 apply_live_preview();
3347 if (ImGui::CollapsingHeader(
"Corner Rounding")) {
3350 if (ImGui::SliderFloat(
"Window Rounding", &edit_theme.
window_rounding,
3351 0.0f, 20.0f,
"%.1f")) {
3352 apply_live_preview();
3355 if (ImGui::SliderFloat(
"Frame Rounding", &edit_theme.
frame_rounding,
3356 0.0f, 12.0f,
"%.1f")) {
3357 apply_live_preview();
3360 if (ImGui::SliderFloat(
"Tab Rounding", &edit_theme.
tab_rounding, 0.0f,
3362 apply_live_preview();
3365 if (ImGui::SliderFloat(
"Scrollbar Rounding",
3368 apply_live_preview();
3371 if (ImGui::SliderFloat(
"Grab Rounding", &edit_theme.
grab_rounding,
3372 0.0f, 12.0f,
"%.1f")) {
3373 apply_live_preview();
3380 if (ImGui::CollapsingHeader(
"Animation Settings")) {
3383 if (ImGui::Checkbox(
"Enable Animations",
3385 apply_live_preview();
3389 if (ImGui::SliderFloat(
"Animation Speed",
3392 apply_live_preview();
3396 if (ImGui::Checkbox(
"Enable Glow Effects",
3398 apply_live_preview();
3404 ImGui::EndTabItem();
3412 if (ImGui::Button(
"Preview Theme")) {
3417 if (ImGui::Button(
"Reset to Current")) {
3423 theme_name[name_len] =
'\0';
3426 sizeof(theme_description) - 1);
3429 theme_description[desc_len] =
'\0';
3434 theme_author[author_len] =
'\0';
3437 if (theme_backup_made) {
3438 theme_backup_made =
false;
3445 if (ImGui::Button(
"Save Theme")) {
3446 edit_theme.
name = std::string(theme_name);
3447 edit_theme.
description = std::string(theme_description);
3448 edit_theme.
author = std::string(theme_author);
3455 theme_backup_made =
false;
3462 bool can_save_over = !current_file_path.empty();
3464 if (!can_save_over) {
3465 ImGui::BeginDisabled();
3468 if (ImGui::Button(
"Save Over Current")) {
3469 edit_theme.
name = std::string(theme_name);
3470 edit_theme.
description = std::string(theme_description);
3471 edit_theme.
author = std::string(theme_author);
3481 LOG_ERROR(
"Theme Manager",
"Failed to save over current theme");
3485 if (!can_save_over) {
3486 ImGui::EndDisabled();
3489 if (ImGui::IsItemHovered() && can_save_over) {
3490 ImGui::BeginTooltip();
3491 ImGui::Text(
"Save over current theme file:");
3492 ImGui::Text(
"%s", current_file_path.c_str());
3493 ImGui::EndTooltip();
3494 }
else if (ImGui::IsItemHovered()) {
3495 ImGui::BeginTooltip();
3496 ImGui::Text(
"No current theme file to overwrite");
3497 ImGui::Text(
"Use 'Save to File...' to create a new theme file");
3498 ImGui::EndTooltip();
3502 if (ImGui::Button(
"Save to File...")) {
3503 edit_theme.
name = std::string(theme_name);
3504 edit_theme.
description = std::string(theme_description);
3505 edit_theme.
author = std::string(theme_author);
3508 std::string safe_name =
3509 edit_theme.
name.empty() ?
"custom_theme" : edit_theme.
name;
3513 if (!file_path.empty()) {
3515 if (file_path.find(
".theme") == std::string::npos) {
3516 file_path +=
".theme";
3525 LOG_ERROR(
"Theme Manager",
"Failed to save theme");
3530 if (ImGui::IsItemHovered()) {
3531 ImGui::BeginTooltip();
3532 ImGui::Text(
"Save theme to a .theme file");
3533 ImGui::Text(
"Saved themes can be shared and loaded later");
3534 ImGui::EndTooltip();