egui/crates/egui_demo_lib/src/demo/code_example.rs

177 lines
4.4 KiB
Rust

#[derive(Debug)]
pub struct CodeExample {
name: String,
age: u32,
}
impl Default for CodeExample {
fn default() -> Self {
Self {
name: "Arthur".to_owned(),
age: 42,
}
}
}
impl CodeExample {
fn samples_in_grid(&mut self, ui: &mut egui::Ui) {
// Note: we keep the code narrow so that the example fits on a mobile screen.
let Self { name, age } = self; // for brevity later on
show_code(ui, r#"ui.heading("Example");"#);
ui.heading("Example");
ui.end_row();
show_code(
ui,
r#"
ui.horizontal(|ui| {
ui.label("Name");
ui.text_edit_singleline(name);
});"#,
);
// Putting things on the same line using ui.horizontal:
ui.horizontal(|ui| {
ui.label("Name");
ui.text_edit_singleline(name);
});
ui.end_row();
show_code(
ui,
r#"
ui.add(
egui::DragValue::new(age)
.clamp_range(0..=120)
.suffix(" years"),
);"#,
);
ui.add(
egui::DragValue::new(age)
.clamp_range(0..=120)
.suffix(" years"),
);
ui.end_row();
show_code(
ui,
r#"
if ui.button("Increment").clicked() {
*age += 1;
}"#,
);
if ui.button("Increment").clicked() {
*age += 1;
}
ui.end_row();
show_code(ui, r#"ui.label(format!("{name} is {age}"));"#);
ui.label(format!("{name} is {age}"));
ui.end_row();
}
fn code(&mut self, ui: &mut egui::Ui) {
show_code(
ui,
r"
pub struct CodeExample {
name: String,
age: u32,
}
impl CodeExample {
fn ui(&mut self, ui: &mut egui::Ui) {
// Saves us from writing `&mut self.name` etc
let Self { name, age } = self;",
);
ui.horizontal(|ui| {
let font_id = egui::TextStyle::Monospace.resolve(ui.style());
let indentation = 8.0 * ui.fonts(|f| f.glyph_width(&font_id, ' '));
let item_spacing = ui.spacing_mut().item_spacing;
ui.add_space(indentation - item_spacing.x);
egui::Grid::new("code_samples")
.striped(true)
.num_columns(2)
.show(ui, |ui| {
self.samples_in_grid(ui);
});
});
crate::rust_view_ui(ui, " }\n}");
}
}
impl super::Demo for CodeExample {
fn name(&self) -> &'static str {
"🖮 Code Example"
}
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
use super::View;
egui::Window::new(self.name())
.open(open)
.min_width(375.0)
.default_size([390.0, 500.0])
.scroll(false)
.resizable([true, false])
.show(ctx, |ui| self.ui(ui));
}
}
impl super::View for CodeExample {
fn ui(&mut self, ui: &mut egui::Ui) {
ui.scope(|ui| {
ui.spacing_mut().item_spacing = egui::vec2(8.0, 8.0);
self.code(ui);
});
ui.separator();
crate::rust_view_ui(ui, &format!("{self:#?}"));
ui.separator();
let mut theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
ui.collapsing("Theme", |ui| {
theme.ui(ui);
theme.store_in_memory(ui.ctx());
});
ui.separator();
ui.vertical_centered(|ui| {
ui.add(crate::egui_github_link_file!());
});
}
}
fn show_code(ui: &mut egui::Ui, code: &str) {
let code = remove_leading_indentation(code.trim_start_matches('\n'));
crate::rust_view_ui(ui, &code);
}
fn remove_leading_indentation(code: &str) -> String {
fn is_indent(c: &u8) -> bool {
matches!(*c, b' ' | b'\t')
}
let first_line_indent = code.bytes().take_while(is_indent).count();
let mut out = String::new();
let mut code = code;
while !code.is_empty() {
let indent = code.bytes().take_while(is_indent).count();
let start = first_line_indent.min(indent);
let end = code
.find('\n')
.map_or_else(|| code.len(), |endline| endline + 1);
out += &code[start..end];
code = &code[end..];
}
out
}