Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,24 @@ static void view_settings_read_line(ImGuiContext *, ImGuiSettingsHandler *,
set_path_setting(view_state->preferences_state.recordings_dir,
sizeof(view_state->preferences_state.recordings_dir),
line + 14);
} else if (strncmp(line, "CustomColor_", 12) == 0) {
int idx;
float r, g, b, a;
if (sscanf(line, "CustomColor_%d=%f,%f,%f,%f", &idx, &r, &g, &b, &a) == 5) {
if (idx >= 0 && idx < ImGuiCol_COUNT) {
g_custom_colors[idx] = ImVec4(r, g, b, a);
g_custom_theme_inited = true;
}
}
} else if (strncmp(line, "CustomAppColor_", 15) == 0) {
int idx;
float r, g, b, a;
if (sscanf(line, "CustomAppColor_%d=%f,%f,%f,%f", &idx, &r, &g, &b, &a) == 5) {
if (idx >= 0 && idx < eAppColor_COUNT) {
g_custom_app_colors[idx] = ImVec4(r, g, b, a);
g_custom_theme_inited = true;
}
}
}
}

Expand Down Expand Up @@ -303,6 +321,17 @@ static void view_settings_write_all(ImGuiContext * /*ctx*/,
buf->appendf("RecordingsDir=%s\n",
view_state->preferences_state.recordings_dir);
}

for (int i = 0; i < ImGuiCol_COUNT; ++i) {
buf->appendf("CustomColor_%d=%.2f,%.2f,%.2f,%.2f\n", i,
g_custom_colors[i].x, g_custom_colors[i].y,
g_custom_colors[i].z, g_custom_colors[i].w);
}
for (int i = 0; i < eAppColor_COUNT; ++i) {
buf->appendf("CustomAppColor_%d=%.2f,%.2f,%.2f,%.2f\n", i,
g_custom_app_colors[i].x, g_custom_app_colors[i].y,
g_custom_app_colors[i].z, g_custom_app_colors[i].w);
}
buf->append("\n");

buf->appendf("[%s][ProcessTable]\n", handler->TypeName);
Expand Down
8 changes: 8 additions & 0 deletions src/style_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ void style_control_select_theme(const Theme theme) {
g_applied_zoom_scale = -1;
}

void style_control_force_update() {
if (g_applied_theme == Theme::COUNT) return;
apply_theme(g_applied_theme, &g_base_style);
apply_geometry(g_base_style);
apply_chart_colormap(g_applied_theme);
g_applied_zoom_scale = -1;
}

void style_control_init(const Theme theme, const float monitor_scale,
const int target_fps) {
register_chart_colormaps();
Expand Down
1 change: 1 addition & 0 deletions src/style_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
void style_control_rebuild(int zoom_pct, int opacity_pct);

void style_control_select_theme(Theme theme);
void style_control_force_update();

void style_control_init(Theme theme, float monitor_scale, int target_fps);

Expand Down
21 changes: 21 additions & 0 deletions src/themes.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ enum class Theme : uint8_t {
Onenord,
EverforestDark,
EverforestLight,
Custom,
COUNT
};

Expand All @@ -42,6 +43,8 @@ inline const char *theme_name(const Theme theme) {
return "Everforest Dark";
case Theme::EverforestLight:
return "Everforest Light";
case Theme::Custom:
return "Custom";
default:
return "Unknown";
}
Expand All @@ -61,6 +64,10 @@ enum AppColor : uint8_t {
// opacity - these are foreground highlights, not panel backgrounds.
inline ImVec4 g_app_colors[eAppColor_COUNT];

inline ImVec4 g_custom_colors[ImGuiCol_COUNT];
inline ImVec4 g_custom_app_colors[eAppColor_COUNT];
inline bool g_custom_theme_inited = false;

inline ImU32 app_color_u32(const AppColor idx) {
return ImGui::ColorConvertFloat4ToU32(g_app_colors[idx]);
}
Expand Down Expand Up @@ -529,6 +536,20 @@ inline void apply_theme(const Theme theme, ImGuiStyle *dst = nullptr) {
break;
}

case Theme::Custom: {
if (!g_custom_theme_inited) {
ImGui::StyleColorsDark(dst);
set_app_colors_dark();
for (int i = 0; i < ImGuiCol_COUNT; ++i) g_custom_colors[i] = colors[i];
for (int i = 0; i < eAppColor_COUNT; ++i) g_custom_app_colors[i] = g_app_colors[i];
g_custom_theme_inited = true;
} else {
for (int i = 0; i < ImGuiCol_COUNT; ++i) colors[i] = g_custom_colors[i];
for (int i = 0; i < eAppColor_COUNT; ++i) g_app_colors[i] = g_custom_app_colors[i];
}
break;
}

default:
ImGui::StyleColorsLight(dst);
set_app_colors_light();
Expand Down
110 changes: 110 additions & 0 deletions src/views/menu_bar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ static const char *PERIOD_LABELS[] = {"Paused", "0.25s", "0.5s",
static const char *PREFERENCES_TITLE = "Preferences";
static const char *ABOUT_TITLE = "About Prock";
static const char *LICENSES_TITLE = "Third-Party Licenses";
static const char *THEME_EDITOR_TITLE = "Theme Editor";
static constexpr float UI_ELEMENT_WIDTH = 220.0f;
static constexpr float FONT_POPUP_WIDTH = 300.0f;
static constexpr float SETTING_LABEL_WIDTH = 130.0f;
Expand Down Expand Up @@ -149,6 +150,106 @@ static void draw_font_picker(PreferencesState &prefs, const char *label,
ImGui::PopID();
}

static void draw_theme_editor_modal(PreferencesState &prefs) {
if (prefs.show_theme_editor_modal) {
ImGui::OpenPopup(THEME_EDITOR_TITLE);
}

const ImVec2 center = ImGui::GetMainViewport()->GetCenter();
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
ImGui::SetNextWindowSize(ImVec2(600.0f * ui_scale(), 500.0f * ui_scale()), ImGuiCond_Appearing);

if (ImGui::BeginPopupModal(THEME_EDITOR_TITLE, &prefs.show_theme_editor_modal)) {
if (popup_close_on_escape()) {
prefs.show_theme_editor_modal = false;
}

static ImGuiTextFilter filter;

ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted(ICON_MD_SEARCH);
ImGui::SameLine();
filter.Draw("##ColorFilter", 200.0f * ui_scale());

ImGui::SameLine(ImGui::GetWindowContentRegionMax().x - 200.0f * ui_scale());
ImGui::SetNextItemWidth(200.0f * ui_scale());
if (ImGui::BeginCombo("##LoadPreset", "Load Preset...")) {
for (int i = 0; i < static_cast<int>(Theme::Custom); i++) {
const Theme t = static_cast<Theme>(i);
if (ImGui::Selectable(theme_name(t))) {
ImGuiStyle temp_style;
apply_theme(t, &temp_style);
for (int j = 0; j < ImGuiCol_COUNT; ++j) {
g_custom_colors[j] = temp_style.Colors[j];
}
for (int j = 0; j < eAppColor_COUNT; ++j) {
g_custom_app_colors[j] = g_app_colors[j];
}
style_control_force_update();
style_control_rebuild(prefs.zoom_scale_pct, prefs.window_opacity_pct);
}
}
ImGui::EndCombo();
}

ImGui::Spacing();

if (ImGui::BeginTabBar("ThemeEditorTabs")) {
if (ImGui::BeginTabItem("ImGui Colors")) {
ImGui::BeginChild("ImGuiColorsScroll", ImVec2(0, -ImGui::GetFrameHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.y));
for (int i = 0; i < ImGuiCol_COUNT; ++i) {
const char* color_name = ImGui::GetStyleColorName(i);
if (!filter.PassFilter(color_name)) continue;

ImGui::PushID(i);
if (ImGui::ColorEdit4(color_name, (float*)&g_custom_colors[i], ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_AlphaPreviewHalf)) {
if (prefs.theme == Theme::Custom) {
style_control_force_update();
style_control_rebuild(prefs.zoom_scale_pct, prefs.window_opacity_pct);
}
}
ImGui::PopID();
}
ImGui::EndChild();
ImGui::EndTabItem();
}

if (ImGui::BeginTabItem("App Colors")) {
ImGui::BeginChild("AppColorsScroll", ImVec2(0, -ImGui::GetFrameHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.y));
static const char* app_color_names[eAppColor_COUNT] = {
"NewProcessRow",
"DeadProcessRow",
"ErrorText",
"WarningText",
"InfoText"
};
for (int i = 0; i < eAppColor_COUNT; ++i) {
if (!filter.PassFilter(app_color_names[i])) continue;

ImGui::PushID(i);
if (ImGui::ColorEdit4(app_color_names[i], (float*)&g_custom_app_colors[i], ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_AlphaPreviewHalf)) {
if (prefs.theme == Theme::Custom) {
style_control_force_update();
style_control_rebuild(prefs.zoom_scale_pct, prefs.window_opacity_pct);
}
}
ImGui::PopID();
}
ImGui::EndChild();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}

if (ImGui::Button("Close", ImVec2(CLOSE_BUTTON_WIDTH * ui_scale(), 0.0f))) {
ImGui::CloseCurrentPopup();
prefs.show_theme_editor_modal = false;
}

ImGui::EndPopup();
}
}

static void draw_preferences_modal(PreferencesState &prefs) {
if (prefs.show_preferences_modal) {
ImGui::OpenPopup(PREFERENCES_TITLE);
Expand Down Expand Up @@ -192,6 +293,14 @@ static void draw_preferences_modal(PreferencesState &prefs) {
}
ImGui::EndCombo();
}

ImGui::SameLine();
if (ImGui::Button("Edit Colors")) {
prefs.theme = Theme::Custom;
changed_style = true;
prefs.show_theme_editor_modal = true;
prefs.show_preferences_modal = false;
}

changed_style |=
input_int("Zoom", prefs.zoom_scale_pct, ZOOM_MIN_PCT, ZOOM_MAX_PCT);
Expand Down Expand Up @@ -502,6 +611,7 @@ void menu_bar_draw(ViewState &view_state) {
}

draw_preferences_modal(view_state.preferences_state);
draw_theme_editor_modal(view_state.preferences_state);
draw_about_modal(view_state.preferences_state);
draw_licenses_modal(view_state.preferences_state);
}
1 change: 1 addition & 0 deletions src/views/menu_bar.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct PreferencesState {
bool show_preferences_modal = false;
bool show_about_modal = false;
bool show_licenses_modal = false;
bool show_theme_editor_modal = false;
bool font_needs_reload = false; // Signal to reload font atlas
bool show_debug_fps = false; // Debug-only FPS overlay; flip in code
bool show_menu_on_alt = false;
Expand Down