use crate::color::{set_alpha_in_place, set_style_alpha}; use eframe::egui; use eframe::egui::{Align2, Color32, Context, Frame, Vec2, Widget, Window}; /// A reusable (pseudo)code-display component. #[derive(Clone)] pub struct Code { /// Must be unique for `egui` reasons. pub name: &'static str, /// Horizontal offset from middle. pub offset_x: f32, /// Vertical offset from middle. pub offset_y: f32, /// How tall and wide. pub size_pixels: f32, /// Background color. Transparent disables background. pub background: Color32, /// Alpha (how opaque) entire widget is. pub alpha: f32, /// Code. pub code: String, } impl Default for Code { fn default() -> Self { Self { name: "grid", offset_x: 0.0, offset_y: 0.0, size_pixels: 400.0, background: Color32::from_rgb(230, 230, 230), alpha: 1.0, code: String::from(r#"println("Hello world!");"#), } } } impl Code { /// Render to UI. pub fn show(&self, ctx: &Context) { Window::new(self.name) .title_bar(false) .frame(Frame::window(&set_style_alpha(&ctx.style(), self.alpha))) .anchor( Align2::CENTER_CENTER, Vec2::new(self.offset_x, self.offset_y), ) .fixed_size(Vec2::splat(self.size_pixels)) .show(ctx, |ui| { // Syntax coloring code adapted from: https://github.com/emilk/egui/blob/master/egui_demo_lib/src/apps/demo/code_editor.rs let theme = egui_demo_lib::syntax_highlighting::CodeTheme::light(); let mut layouter = |ui: &egui::Ui, string: &str, wrap_width: f32| { let mut layout_job = egui_demo_lib::syntax_highlighting::highlight( ui.ctx(), &theme, string, "rs", ); for section in &mut layout_job.sections { set_alpha_in_place(&mut section.format.color, self.alpha); } layout_job.wrap_width = wrap_width; ui.fonts().layout_job(layout_job) }; egui::TextEdit::multiline(&mut self.code.as_str()) .font(egui::TextStyle::Monospace) // Only affects cursor. .code_editor() .lock_focus(true) .desired_width(f32::INFINITY) .layouter(&mut layouter) .ui(ui); }); } } /// Converts Rust code to pseudocode. /// /// Note: Must use non-idiomatic `return x;` instead of just `x`. pub fn pseudocode(code: &str) -> String { code.replace("pub ", "") .replace("fn ", "function ") .replace("let ", "") .replace("mut ", "") .replace(": f32", "") .replace(" -> bool", "") .replace("println!", "println") .replace(";\n", "\n") }