use crate::app::TextEditor; use crate::ui::constants::*; use eframe::egui; pub(crate) fn preferences_window(app: &mut TextEditor, ctx: &egui::Context) { let visuals = &ctx.style().visuals; let screen_rect = ctx.screen_rect(); let window_width = (screen_rect.width() * WINDOW_WIDTH_RATIO) .clamp(WINDOW_MIN_WIDTH, WINDOW_MAX_WIDTH); let window_height = (screen_rect.height() * WINDOW_HEIGHT_RATIO) .clamp(WINDOW_MIN_HEIGHT, WINDOW_MAX_HEIGHT); let max_size = egui::Vec2::new(window_width, window_height); egui::Window::new("Preferences") .collapsible(false) .resizable(false) .anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO) .default_open(true) .max_size(max_size) .fade_in(true) .fade_out(true) .frame(egui::Frame { fill: visuals.window_fill, stroke: visuals.window_stroke, corner_radius: egui::CornerRadius::same(CORNER_RADIUS), shadow: visuals.window_shadow, inner_margin: egui::Margin::same(INNER_MARGIN), outer_margin: egui::Margin::same(0), }) .show(ctx, |ui| { ui.vertical_centered(|ui| { ui.heading("Editor Settings"); ui.add_space(MEDIUM); ui.horizontal(|ui| { ui.vertical(|ui| { if ui .checkbox(&mut app.state_cache, "Maintain State") .on_hover_text("Unsaved changes will be cached between sessions") .changed() { app.save_config(); if !app.state_cache { if let Err(e) = TextEditor::clear_state_cache() { eprintln!("Failed to clear state cache: {e}"); } } } ui.add_space(SMALL); if ui .checkbox(&mut app.show_line_numbers, "Show Line Numbers") .changed() { app.save_config(); } ui.add_space(SMALL); if ui .checkbox(&mut app.auto_hide_toolbar, "Auto Hide Toolbar") .on_hover_text( "Hide the top bar until you move your mouse to the upper edge", ) .changed() { app.save_config(); } }); ui.vertical(|ui| { if ui.checkbox(&mut app.word_wrap, "Word Wrap").changed() { app.save_config(); } ui.add_space(SMALL); if ui .checkbox(&mut app.syntax_highlighting, "Syntax Highlighting") .changed() { app.save_config(); } ui.add_space(SMALL); if ui .checkbox(&mut app.hide_tab_bar, "Hide Tab Bar") .on_hover_text( "Hide the tab bar and show tab title in menu bar instead", ) .changed() { app.save_config(); } }); }); ui.add_space(SMALL); ui.separator(); ui.add_space(LARGE); ui.heading("Font Settings"); ui.add_space(MEDIUM); ui.horizontal(|ui| { ui.vertical(|ui| { ui.label("Font Family:"); ui.add_space(SMALL); ui.label("Font Size:"); }); ui.vertical(|ui| { let mut changed = false; egui::ComboBox::from_id_salt("font_family") .selected_text(&app.font_family) .show_ui(ui, |ui| { if ui .selectable_value( &mut app.font_family, "Proportional".to_string(), "Proportional", ) .clicked() { changed = true; } if ui .selectable_value( &mut app.font_family, "Monospace".to_string(), "Monospace", ) .clicked() { changed = true; } }); if app.font_size_input.is_none() { app.font_size_input = Some(app.font_size.to_string()); } let mut font_size_text = app .font_size_input .as_ref() .unwrap_or(&DEFAULT_FONT_SIZE_STR.to_string()) .to_owned(); ui.add_space(SMALL); ui.horizontal(|ui| { let response = ui.add( egui::TextEdit::singleline(&mut font_size_text) .desired_width(FONT_SIZE_INPUT_WIDTH) .hint_text(DEFAULT_FONT_SIZE_STR) .id(egui::Id::new("font_size_input")), ); app.font_size_input = Some(font_size_text.to_owned()); if response.clicked() { response.request_focus(); } ui.label("px"); if response.lost_focus() { if let Ok(new_size) = font_size_text.parse::() { let clamped_size = new_size.clamp(MIN_FONT_SIZE, MAX_FONT_SIZE); if (app.font_size - clamped_size).abs() > 0.1 { app.font_size = clamped_size; app.apply_font_settings(ctx); } } app.font_size_input = None; } if changed { app.apply_font_settings(ctx); } }) }); }); ui.add_space(MEDIUM); ui.label("Preview:"); ui.add_space(SMALL); egui::ScrollArea::vertical() .max_height(PREVIEW_AREA_MAX_HEIGHT) .show(ui, |ui| { egui::Frame::new() .fill(visuals.code_bg_color) .stroke(visuals.widgets.noninteractive.bg_stroke) .inner_margin(egui::Margin::same(INNER_MARGIN)) .show(ui, |ui| { let preview_font = egui::FontId::new( app.font_size, match app.font_family.as_str() { "Monospace" => egui::FontFamily::Monospace, _ => egui::FontFamily::Proportional, }, ); ui.label( egui::RichText::new( "The quick brown fox jumps over the lazy dog.", ) .font(preview_font.to_owned()), ); ui.label( egui::RichText::new("ABCDEFGHIJKLMNOPQRSTUVWXYZ") .font(preview_font.to_owned()), ); ui.label( egui::RichText::new("abcdefghijklmnopqrstuvwxyz") .font(preview_font.to_owned()), ); ui.label( egui::RichText::new("1234567890 !@#$%^&*()") .font(preview_font.to_owned()), ); }); }); ui.add_space(LARGE); if ui.button("Close").clicked() { app.show_preferences = false; app.font_size_input = None; } }); }); }