use eframe::egui;
use egui_ltreeview::TreeView;
#[derive(Debug, Clone, Copy, PartialEq)]
enum SettingsCategory {
General,
UI,
}
impl SettingsCategory {
fn as_str(&self) -> &'static str {
match self {
SettingsCategory::General => "General",
SettingsCategory::UI => "UI",
}
}
fn from_str(s: &str) -> Option<Self> {
match s {
"General" => Some(SettingsCategory::General),
"UI" => Some(SettingsCategory::UI),
_ => None,
}
}
}
#[derive(serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct AppSettings {
pub fps: f32,
pub loop_enabled: bool,
pub current_shader: String,
pub show_help: bool,
pub show_playlist: bool,
pub dark_mode: bool,
pub font_size: f32,
pub cache_mem_percent: f32, pub workers_override: u32,
pub encoder_settings: crate::encode::EncoderSettings,
pub selected_settings_category: Option<String>,
}
impl Default for AppSettings {
fn default() -> Self {
Self {
fps: 24.0,
loop_enabled: true,
current_shader: "default".to_string(),
show_help: true,
show_playlist: true,
dark_mode: true,
font_size: 13.0,
cache_mem_percent: 75.0,
workers_override: 0,
encoder_settings: crate::encode::EncoderSettings::default(),
selected_settings_category: Some("UI".to_string()),
}
}
}
fn render_general_settings(ui: &mut egui::Ui, _settings: &mut AppSettings) {
ui.label("(No settings yet)");
ui.add_space(8.0);
ui.label("General settings will be added here in the future.");
}
fn render_ui_settings(ui: &mut egui::Ui, settings: &mut AppSettings) {
ui.heading("Appearance");
ui.add_space(8.0);
ui.label("Font Size:");
ui.add(
egui::Slider::new(&mut settings.font_size, 10.0..=18.0)
.suffix(" px")
.step_by(0.5)
);
ui.add_space(16.0);
ui.checkbox(&mut settings.dark_mode, "Dark Mode");
ui.add_space(16.0);
ui.heading("Performance");
ui.add_space(8.0);
ui.label("Cache Memory Budget:");
ui.add(
egui::Slider::new(&mut settings.cache_mem_percent, 5.0..=95.0)
.suffix(" %")
.step_by(1.0)
);
ui.label("Applies immediately. Controls the fraction of available RAM used by the frame cache.");
ui.add_space(8.0);
ui.label("Worker Threads Override (0 = Auto):");
ui.add(
egui::DragValue::new(&mut settings.workers_override)
.speed(1.0)
.range(0..=256)
);
ui.label("Takes effect on next launch. Defaults to ~75% of CPU cores.");
}
pub fn render_settings_window(
ctx: &egui::Context,
show_settings: &mut bool,
settings: &mut AppSettings,
) {
let mut selected = settings
.selected_settings_category
.as_ref()
.and_then(|s| SettingsCategory::from_str(s))
.unwrap_or(SettingsCategory::UI);
egui::Window::new("Settings")
.id(egui::Id::new("settings_window"))
.open(show_settings)
.default_size([700.0, 500.0])
.min_size([500.0, 400.0])
.resizable(true)
.collapsible(false)
.show(ctx, |ui| {
egui::ScrollArea::both()
.auto_shrink([false; 2])
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.vertical(|ui| {
ui.set_width(200.0);
ui.add_space(4.0);
let tree_id = ui.make_persistent_id("settings_tree_view");
let (_response, actions) = TreeView::new(tree_id).show(ui, |builder| {
builder.leaf(0, SettingsCategory::General.as_str());
builder.leaf(1, SettingsCategory::UI.as_str());
});
for action in actions {
if let egui_ltreeview::Action::SetSelected(node_ids) = action {
if let Some(&node_id) = node_ids.iter().next() {
selected = match node_id {
0 => SettingsCategory::General,
1 => SettingsCategory::UI,
_ => selected,
};
}
}
}
});
ui.separator();
ui.vertical(|ui| {
ui.add_space(8.0);
match selected {
SettingsCategory::General => render_general_settings(ui, settings),
SettingsCategory::UI => render_ui_settings(ui, settings),
}
});
});
});
});
settings.selected_settings_category = Some(selected.as_str().to_string());
}