use eframe::egui; /// Modern dark purple color palette pub struct ColorPalette { // Background colors pub bg_primary: egui::Color32, // Main background pub bg_secondary: egui::Color32, // Secondary panels pub bg_tertiary: egui::Color32, // Elevated elements // Accent colors pub accent_primary: egui::Color32, // Primary purple accent pub accent_secondary: egui::Color32, // Secondary accent pub accent_bright: egui::Color32, // Bright highlights // Text colors pub text_primary: egui::Color32, pub text_secondary: egui::Color32, pub text_muted: egui::Color32, // UI element colors pub selection: egui::Color32, pub line_number: egui::Color32, pub border: egui::Color32, } impl ColorPalette { pub fn dark_purple() -> Self { Self { // Deep purple-gray backgrounds bg_primary: egui::Color32::from_rgb(24, 20, 32), // #18141F bg_secondary: egui::Color32::from_rgb(32, 26, 42), // #201A2A bg_tertiary: egui::Color32::from_rgb(42, 35, 54), // #2A2336 // Purple accents - modern and vibrant accent_primary: egui::Color32::from_rgb(138, 98, 208), // #8A62D0 accent_secondary: egui::Color32::from_rgb(108, 68, 178), // #6C44B2 accent_bright: egui::Color32::from_rgb(168, 128, 238), // #A880EE // Text colors with good contrast text_primary: egui::Color32::from_rgb(230, 230, 240), // #E6E6F0 text_secondary: egui::Color32::from_rgb(190, 190, 210), // #BEBED2 text_muted: egui::Color32::from_rgb(140, 140, 165), // #8C8CA5 // UI elements selection: egui::Color32::from_rgb(108, 68, 178), // #6C44B2 line_number: egui::Color32::from_rgb(110, 100, 130), // #6E6482 border: egui::Color32::from_rgb(60, 50, 75), // #3C324B } } } /// Apply the dark purple theme to the egui context pub fn apply_theme(ctx: &egui::Context) { let palette = ColorPalette::dark_purple(); let mut style = (*ctx.style()).clone(); // === Spacing and sizing for better UX === style.spacing.item_spacing = egui::vec2(8.0, 6.0); style.spacing.button_padding = egui::vec2(12.0, 6.0); style.spacing.menu_margin = egui::Margin::same(8.0); style.spacing.indent = 20.0; style.spacing.scroll = egui::style::ScrollStyle { bar_width: 10.0, handle_min_length: 20.0, bar_inner_margin: 2.0, bar_outer_margin: 0.0, ..Default::default() }; // === Color scheme === let visuals = &mut style.visuals; // Dark mode visuals.dark_mode = true; // Window and panel backgrounds visuals.window_fill = palette.bg_primary; visuals.panel_fill = palette.bg_primary; visuals.faint_bg_color = palette.bg_secondary; visuals.extreme_bg_color = palette.bg_tertiary; // Text colors (using override_text_color to set custom text color) visuals.override_text_color = Some(palette.text_primary); // Widget colors visuals.widgets.noninteractive.bg_fill = palette.bg_secondary; visuals.widgets.noninteractive.weak_bg_fill = palette.bg_secondary; visuals.widgets.noninteractive.bg_stroke = egui::Stroke::new(1.0, palette.border); visuals.widgets.noninteractive.fg_stroke = egui::Stroke::new(1.0, palette.text_secondary); // Inactive/hovered widgets visuals.widgets.inactive.bg_fill = palette.bg_secondary; visuals.widgets.inactive.weak_bg_fill = palette.bg_secondary; visuals.widgets.inactive.bg_stroke = egui::Stroke::new(1.0, palette.border); visuals.widgets.inactive.fg_stroke = egui::Stroke::new(1.0, palette.text_primary); visuals.widgets.hovered.bg_fill = palette.bg_tertiary; visuals.widgets.hovered.weak_bg_fill = palette.bg_tertiary; visuals.widgets.hovered.bg_stroke = egui::Stroke::new(1.5, palette.accent_primary); visuals.widgets.hovered.fg_stroke = egui::Stroke::new(1.5, palette.text_primary); // Active/clicked widgets visuals.widgets.active.bg_fill = palette.accent_secondary; visuals.widgets.active.weak_bg_fill = palette.accent_secondary; visuals.widgets.active.bg_stroke = egui::Stroke::new(2.0, palette.accent_bright); visuals.widgets.active.fg_stroke = egui::Stroke::new(2.0, palette.text_primary); visuals.widgets.open.bg_fill = palette.accent_secondary; visuals.widgets.open.weak_bg_fill = palette.accent_secondary; visuals.widgets.open.bg_stroke = egui::Stroke::new(1.5, palette.accent_primary); visuals.widgets.open.fg_stroke = egui::Stroke::new(1.5, palette.text_primary); // Selection visuals.selection.bg_fill = palette.selection; visuals.selection.stroke = egui::Stroke::new(1.0, palette.accent_bright); // Hyperlinks visuals.hyperlink_color = palette.accent_bright; // Window styling visuals.window_rounding = egui::Rounding::same(8.0); visuals.window_shadow = egui::epaint::Shadow { offset: egui::vec2(0.0, 8.0), blur: 20.0, spread: 0.0, color: egui::Color32::from_black_alpha(80), }; visuals.window_stroke = egui::Stroke::new(1.0, palette.border); // Popup styling visuals.popup_shadow = egui::epaint::Shadow { offset: egui::vec2(0.0, 4.0), blur: 16.0, spread: 0.0, color: egui::Color32::from_black_alpha(100), }; // Resize handle visuals.resize_corner_size = 12.0; // Menu rounding visuals.menu_rounding = egui::Rounding::same(6.0); // Indent guide visuals.indent_has_left_vline = true; visuals.striped = true; // Borders and separators visuals.window_stroke = egui::Stroke::new(1.0, palette.border); // === Text styles with better readability === style.text_styles.insert( egui::TextStyle::Body, egui::FontId::proportional(14.0), ); style.text_styles.insert( egui::TextStyle::Button, egui::FontId::proportional(14.0), ); style.text_styles.insert( egui::TextStyle::Heading, egui::FontId::proportional(18.0), ); style.text_styles.insert( egui::TextStyle::Monospace, egui::FontId::monospace(13.0), ); // Apply the style ctx.set_style(style); } /// Get the color palette for use in custom rendering pub fn get_palette() -> ColorPalette { ColorPalette::dark_purple() }